void reverse(char *str){ int i,j; char temp; for(i=0,j=strlen(str)-1; i<j; i++, j--){ temp = *(str + i); *(str + i) = *(str + j); *(str + j) = temp; printf("%c",*(str + j)); } }
int main (int argc, char const *argv[]) { char *str = "Shiv"; reverse(str); printf("%s",str); return 0; }
When I use char *str = "Shiv" the lines in the swapping part of my reverse function i.e str[i]=str[j] dont seem to work, however if I declare str as char str[] = "Shiv", the swapping part works? What is the reason for this. I was a bit puzzled by the behavior, I kept getting the message "Bus error" when I tried to run the program.
当我使用char *str = "Shiv"时,我的反向函数的交换部分中的行。e str[i]=str[j]似乎不工作,但如果我将str声明为char str[] = "Shiv",交换部分是否工作?原因是什么?我对这种行为有点迷惑,当我试图运行程序时,我不断地收到“总线错误”的消息。
8 个解决方案
#1
16
When you use char *str = "Shiv";
, you don't own the memory pointed to, and you're not allowed to write to it. The actual bytes for the string could be a constant inside the program's code.
当您使用char *str = "Shiv"时,您不会拥有指向的内存,并且您不能写入它。字符串的实际字节可以是程序代码中的常量。
When you use char str[] = "Shiv";
, the 4(+1) char bytes and the array itself are on your stack, and you're allowed to write to them as much as you please.
当您使用char str[] = "Shiv"时,4(+1)char字节和数组本身就在您的堆栈上,您可以随意地对它们进行写入。
#2
4
The char *str = "Shiv" gets a pointer to a string constant, which may be loaded into a protected area of memory (e.g. part of the executable code) that is read only.
char *str = "Shiv"获取指向字符串常量的指针,该常量可以加载到仅读取的内存保护区域(例如可执行代码的一部分)。
#3
4
char *str = "Shiv";
This should be :
这应该是:
const char *str = "Shiv";
And now you'll have an error ;)
现在你会有一个错误;
#4
1
Try
试一试
int main (int argc, char const *argv[])
{
char *str = malloc(5*sizeof(char)); //4 chars + '\0'
strcpy(str,"Shiv");
reverse(str);
printf("%s",str);
free(str); //Not needed for such a small example, but to illustrate
return 0;
}
instead. That will get you read/write memory when using pointers. Using [] notation allocates space in the stack directly, but using const pointers doesn't.
代替。这将使您在使用指针时获得读/写内存。使用[]表示法直接分配堆栈中的空间,但使用const指针则不行。
#5
1
String literals are non-modifiable objects in both C and C++. An attempt to modify a string literal always results in undefined behavior. This is exactly what you observe when you get your "Bus error" with
字符串常量在C和c++中都是不可修改的对象。试图修改字符串文字总是导致未定义的行为。这正是您在得到“总线错误”时所观察到的
char *str = "Shiv";
variant. In this case your 'reverse' function will make an attempt to modify a string literal. Thus, the behavior is undefined.
变体。在这种情况下,您的“反向”函数将尝试修改字符串文字。因此,行为没有定义。
The
的
char str[] = "Shiv";
variant will create a copy of the string literal in a modifiable array 'str', and then 'reverse' will operate on that copy. This will work fine.
变量将在可修改的数组“str”中创建字符串文字的副本,然后“reverse”将对该副本进行操作。这将工作良好。
P.S. Don't create non-const-qualified pointers to string literals. You first variant should have been
注意,不要为字符串文字创建非conconst限定的指针。您的第一个变体应该是
const char *str = "Shiv";
(note the extra 'const').
(注意额外的“常量”)。
#6
1
String literals (your "Shiv") are not modifiable.
You assign to a pointer the address of such a string literal, then you try to change the contents of the string literal by dereferencing the pointer value. That's a big NO-NO.
字符串文字(您的“Shiv”)是不可修改的。您将这样一个字符串字面量的地址分配给一个指针,然后尝试通过取消对指针值的引用来更改字符串字面量的内容。这是一个很大的禁忌。
Declare str as an array instead:
将str作为一个数组声明:
char str[] = "Shiv";
This creates str as an array of 5 characters and copies the characters 'S', 'h', 'i', 'v' and '\0' to str[0], str[1], ..., str[4]. The values in each element of str
are modifiable.
这将创建一个由5个字符组成的str,并将字符'S'、'h'、'i'、'v'和'\0'复制到str[0]、str[1]……str[4]。str的每个元素中的值都是可修改的。
When I want to use a pointer to a string literal, I usually declare it const
. That way, the compiler can help me by issuing a message when my code wants to change the contents of a string literal
当我想要使用一个指向字符串文字的指针时,我通常会声明它是const。这样,当我的代码想要更改字符串文本的内容时,编译器就可以帮助我发出一条消息。
const char *str = "Shiv";
Imagine you could do the same with integers.
假设你可以对整数做同样的事情。
/* Just having fun, this is not C! */
int *ptr = &5; /* address of 5 */
*ptr = 42; /* change 5 to 42 */
printf("5 + 1 is %d\n", *(&5) + 1); /* 6? or 43? :) */
Quote from the Standard:
引用标准:
6.4.5 String literals
...
6 ... If the program attempts to modify such an array [a string literal], the behavior is undefined.6.4.5字符串文字……6……如果程序试图修改这样一个数组[字符串字面量],则该行为是未定义的。
#7
0
char *str is a pointer / reference to a block of characters (the string). But its sitting somewhere in a block of memory so you cannot just assign it like that.
char *str是指向字符块(字符串)的指针/引用。但是它位于内存块的某个地方所以你不能像这样分配它。
#8
0
Interesting that I've never noticed this. I was able to replicate this condition in VS2008 C++.
有趣的是我从来没有注意到这一点。我能够在VS2008 c++中复制这种情况。
Typically, it is a bad idea to do in-place modification of constants.
通常,对常量进行就地修改是个坏主意。
In any case, this post explains this situation pretty clearly.
无论如何,这篇文章非常清楚地解释了这种情况。
The first (char[]) is local data you can edit (since the array is local data).
第一个(char[])是可以编辑的本地数据(因为数组是本地数据)。
The second (char *) is a local pointer to global, static (constant) data. You are not allowed to modify constant data.
第二个(char *)是指向全局、静态(常量)数据的本地指针。不允许修改常量数据。
If you have GNU C, you can compile with -fwritable-strings to keep the global string from being made constant, but this is not recommended.
如果您有GNU C,您可以使用-fwritable-strings进行编译,以避免使全局字符串成为常量,但不建议这样做。
#1
16
When you use char *str = "Shiv";
, you don't own the memory pointed to, and you're not allowed to write to it. The actual bytes for the string could be a constant inside the program's code.
当您使用char *str = "Shiv"时,您不会拥有指向的内存,并且您不能写入它。字符串的实际字节可以是程序代码中的常量。
When you use char str[] = "Shiv";
, the 4(+1) char bytes and the array itself are on your stack, and you're allowed to write to them as much as you please.
当您使用char str[] = "Shiv"时,4(+1)char字节和数组本身就在您的堆栈上,您可以随意地对它们进行写入。
#2
4
The char *str = "Shiv" gets a pointer to a string constant, which may be loaded into a protected area of memory (e.g. part of the executable code) that is read only.
char *str = "Shiv"获取指向字符串常量的指针,该常量可以加载到仅读取的内存保护区域(例如可执行代码的一部分)。
#3
4
char *str = "Shiv";
This should be :
这应该是:
const char *str = "Shiv";
And now you'll have an error ;)
现在你会有一个错误;
#4
1
Try
试一试
int main (int argc, char const *argv[])
{
char *str = malloc(5*sizeof(char)); //4 chars + '\0'
strcpy(str,"Shiv");
reverse(str);
printf("%s",str);
free(str); //Not needed for such a small example, but to illustrate
return 0;
}
instead. That will get you read/write memory when using pointers. Using [] notation allocates space in the stack directly, but using const pointers doesn't.
代替。这将使您在使用指针时获得读/写内存。使用[]表示法直接分配堆栈中的空间,但使用const指针则不行。
#5
1
String literals are non-modifiable objects in both C and C++. An attempt to modify a string literal always results in undefined behavior. This is exactly what you observe when you get your "Bus error" with
字符串常量在C和c++中都是不可修改的对象。试图修改字符串文字总是导致未定义的行为。这正是您在得到“总线错误”时所观察到的
char *str = "Shiv";
variant. In this case your 'reverse' function will make an attempt to modify a string literal. Thus, the behavior is undefined.
变体。在这种情况下,您的“反向”函数将尝试修改字符串文字。因此,行为没有定义。
The
的
char str[] = "Shiv";
variant will create a copy of the string literal in a modifiable array 'str', and then 'reverse' will operate on that copy. This will work fine.
变量将在可修改的数组“str”中创建字符串文字的副本,然后“reverse”将对该副本进行操作。这将工作良好。
P.S. Don't create non-const-qualified pointers to string literals. You first variant should have been
注意,不要为字符串文字创建非conconst限定的指针。您的第一个变体应该是
const char *str = "Shiv";
(note the extra 'const').
(注意额外的“常量”)。
#6
1
String literals (your "Shiv") are not modifiable.
You assign to a pointer the address of such a string literal, then you try to change the contents of the string literal by dereferencing the pointer value. That's a big NO-NO.
字符串文字(您的“Shiv”)是不可修改的。您将这样一个字符串字面量的地址分配给一个指针,然后尝试通过取消对指针值的引用来更改字符串字面量的内容。这是一个很大的禁忌。
Declare str as an array instead:
将str作为一个数组声明:
char str[] = "Shiv";
This creates str as an array of 5 characters and copies the characters 'S', 'h', 'i', 'v' and '\0' to str[0], str[1], ..., str[4]. The values in each element of str
are modifiable.
这将创建一个由5个字符组成的str,并将字符'S'、'h'、'i'、'v'和'\0'复制到str[0]、str[1]……str[4]。str的每个元素中的值都是可修改的。
When I want to use a pointer to a string literal, I usually declare it const
. That way, the compiler can help me by issuing a message when my code wants to change the contents of a string literal
当我想要使用一个指向字符串文字的指针时,我通常会声明它是const。这样,当我的代码想要更改字符串文本的内容时,编译器就可以帮助我发出一条消息。
const char *str = "Shiv";
Imagine you could do the same with integers.
假设你可以对整数做同样的事情。
/* Just having fun, this is not C! */
int *ptr = &5; /* address of 5 */
*ptr = 42; /* change 5 to 42 */
printf("5 + 1 is %d\n", *(&5) + 1); /* 6? or 43? :) */
Quote from the Standard:
引用标准:
6.4.5 String literals
...
6 ... If the program attempts to modify such an array [a string literal], the behavior is undefined.6.4.5字符串文字……6……如果程序试图修改这样一个数组[字符串字面量],则该行为是未定义的。
#7
0
char *str is a pointer / reference to a block of characters (the string). But its sitting somewhere in a block of memory so you cannot just assign it like that.
char *str是指向字符块(字符串)的指针/引用。但是它位于内存块的某个地方所以你不能像这样分配它。
#8
0
Interesting that I've never noticed this. I was able to replicate this condition in VS2008 C++.
有趣的是我从来没有注意到这一点。我能够在VS2008 c++中复制这种情况。
Typically, it is a bad idea to do in-place modification of constants.
通常,对常量进行就地修改是个坏主意。
In any case, this post explains this situation pretty clearly.
无论如何,这篇文章非常清楚地解释了这种情况。
The first (char[]) is local data you can edit (since the array is local data).
第一个(char[])是可以编辑的本地数据(因为数组是本地数据)。
The second (char *) is a local pointer to global, static (constant) data. You are not allowed to modify constant data.
第二个(char *)是指向全局、静态(常量)数据的本地指针。不允许修改常量数据。
If you have GNU C, you can compile with -fwritable-strings to keep the global string from being made constant, but this is not recommended.
如果您有GNU C,您可以使用-fwritable-strings进行编译,以避免使全局字符串成为常量,但不建议这样做。