2013-08-28 5 views
1

Я пытаюсь написать обратную функцию на месте и достаточно точно выполнить сетевой код, но при запуске следующей программы выдается ошибка шины. Я передаю неправильный аргумент reverse()?Сегментация Неисправность при записи строки

void reverse(char *str) { 
    char * end = str; 
    char tmp; 
    if (str) { 
     while (*end) { 
      ++end; 
     } 
     --end; 
     while (str < end) { 
      tmp = *str; 
      *str++ = *end; 
      *end-- = tmp; 
     } 
    } 
} 

int main() { 
    char *s = "sample"; 
    reverse(s); 
    printf("%s\n"); 
    return 1; 
} 
+0

Я абсолютно уверен, вы имели в виду 'Е ("% s \ п", с);'. – cHao

+0

Вы должны были написать 'const char * s =" sample ";'. Понял? Вы знаете, почему строковые константы называются константами? Нет? Лучше google это. –

ответ

4

Вы можете захотеть изменить

char *s = "sample"; //Pointer to string literal 

в

char s[] = "sample"; // mutable copy of string literal 

Это неопределенное поведение, чтобы попытаться изменить строковые литералы, они должны быть использованы в качестве const char *.


Вероятно, не связаны, но предположение,

Когда вы делаете что-то вроде *end--, вы можете поставить paranthesis так, что он делает то, что вы думаете, что он делает.

выше может быть

(*end)-- 

или

*(end--) 

И вам нужно хорошее знание правил приоритета, чтобы быть уверенным, что вы хотите, это то, что происходит.

+0

UB в C, так что этот ответ правильный о том, почему авария. Но исходный код верен с точки зрения приоритета; оператор разыменования имеет более низкий приоритет, чем приращение/декремент постфикса. – verbose

+0

@verbose спасибо, я больше знаком с C++, так что не был уверен –

3

Ваша обратная функция совершенно правильная. Лишь немногое, что с вашей основной частью функции:

  • как сказал KarthikT, s должна быть char[] не char*, потому что изменение буквальным является неопределенным.

  • в вашей функции printf, вы забыли поместить s в качестве параметра.

  • return 0 удался. return 1 - погрешность.

Таким образом, новый главный должен быть как:

int main() { 
    char s[] = "sample"; 
    reverse(s); 
    printf("%s\n", s); 
    return 0; 
} 

Выход:

elpmas 
14

Чтобы узнать, что происходит, вы должны понять структуру памяти программы C.

char *s = "sample"; // Here the "sample" string is placed in 
         // the read only memory of the Initialized Data segment. 

Здесь вы не можете изменять данные. «s» является указателем на char const («образец»), и вы пытаетесь изменить char const. Вот почему вы получаете ошибку bus error.

     |Stack frame of main()   | 
         |char *s      | 
         |-------------------------------| 
         |Stack frame of reverse()  | 
         |char *end      | 
         |char tmp      | 
         |        | 
         |-------------------------------| 
         |        | 
         |        | 
         |        | 
         |        | 
         |        | 
         |-------------------------------| 
         |        | 
         |   HEAP    | 
         |        | 
         |-------------------------------| 
         |        | 
         | UNINITIALIZED DATA (BSS) | 
         |        | 
         |-------------------------------| 
         |        | 
         |  INITIALIZED DATA   | 
         |        | 
         |"sample" |     | 
         |   |     | 
         |(Read Only)| (Read/Write)  | 
         |-------------------------------| 
         | Text or Code Segment  | 
         |        | 
         |-------------------------------| 

UPDATE Ниже пост не имеет отношения к вашему вопросу.Но если вы знаете, где память, выделенная для всех переменных в C, вы можете лучше кода. Нижеприведенная программа дает лучшее представление о макете памяти программы C. Я не включил аргументы командной строки, аргумент функции и возвращаемые значения функции на диаграмме. Люди, которые хотят обновить это сообщение, могут добавить в диаграмму аргументы командной строки, аргумент функции и вернуть значения функции.

|Stack frame of main()    |    
|local_To_Main      | 
|         | #include <stdio.h> 
|-----------------------------------| #include <stdlib.h> 
|Stack frame of function1()   | int gVariable1 = 100; 
|local_To_Function1     | int gVariable2; 
|iptr        | char cstring[10] = "Hello"; 
|  \    STACK   | char* cptr = "Hello World"; 
|------\---------------|------------| void function1(void) 
|  \    \|/   | { 
|  \       |  static int j = 5; 
|   \       |  int local_To_Function1; 
|   \    ^ |  int *iptr; 
|   \    |  |  iptr = (int *) malloc(sizeof(int)); 
|------------\---------------|------|  free(iptr); 
| HEAP  \  ---   | } 
|    \---> |int|   | 
|      ---   | int main(void) 
|-----------------------------------| { 
|         |  static int i; 
| UNINITIALIZED DATA (BSS)  |  int local_To_Main; 
|gVariable2(initialized to 0)  | 
|i (initialized to 0)    | 
|-----------------------------------|  function1(); 
|         |  return 0; 
|  INITIALIZED DATA    | } 
|         | 
|"Hello World" |gVariable1 =100 | 
|  ^  |cstring="Hello" | 
|  |  |j=5    | 
|  |---<---<---- cptr   | 
|(Read Only) | (Read/Write)  | 
|-----------------------------------| 
| Text or Code Segment   | 
|         | 
|-----------------------------------| 
1
char *str="sample"; 

Здесь образец хранится в памяти только для чтения, так что вы никогда не можете вносить изменения на таких литералов.

Для того, чтобы делать манипуляции, вы должны хранить литералы в памяти чтения-записи. Данный код может решить вашу проблему.

#include<stdio.h> 
void reverse(char *str) 
{ 
    char temp,*end; 
    for(end=str;*end;end++); 
    end--; 
    for(;str<end;temp=*str,*(str++)=*end,*(end--)=temp); 
} 

int main() 
{ 
    char str[]="sample"; //stored in read-write memory 
    reverse(str); 
    printf("%s\n",str); 
return 0; 
} 

Выход:

elpmas 
Смежные вопросы