为什么 *(str+i) = *(str +j) 在这里不起作用?
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; }
当我使用 char *str = "Shiv" 时,反向函数的交换部分中的行(即 str[i]=str[j] )似乎不起作用,但是如果我将 str 声明为 char str[] = "Shiv",交换部分有效吗?这是什么原因呢。我对这种行为有点困惑,当我尝试运行该程序时,我不断收到“总线错误”消息。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
当您使用 char *str = "Shiv"; 时,您不拥有所指向的内存,并且不允许对其进行写入。字符串的实际字节可以是程序代码中的常量。
当您使用 char str[] = "Shiv"; 时,4(+1) 个字符字节和数组本身都在堆栈上,并且您可以向它们写入尽可能多的内容请。
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.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" 获取指向字符串常量的指针,该常量可以加载到只读的内存受保护区域(例如,可执行代码的一部分)。
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.
这应该是:
现在你会遇到一个错误;)
This should be :
And now you'll have an error ;)
尝试
一下。这将使您在使用指针时读/写内存。使用 [] 表示法直接在堆栈中分配空间,但使用 const 指针则不会。
Try
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.
在 C 和 C++ 中,字符串文字都是不可修改的对象。尝试修改字符串文字总是会导致未定义的行为。这正是您在收到
变体“总线错误”时所观察到的情况。在这种情况下,您的“反向”函数将尝试修改字符串文字。因此,行为是未定义的。
该
变体将在可修改数组“str”中创建字符串文字的副本,然后“reverse”将对该副本进行操作。这会工作得很好。
PS 不要创建指向字符串文字的非 const 限定指针。你的第一个变体应该是
(注意额外的“const”)。
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
variant. In this case your 'reverse' function will make an attempt to modify a string literal. Thus, the behavior is undefined.
The
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.
P.S. Don't create non-const-qualified pointers to string literals. You first variant should have been
(note the extra 'const').
字符串文字(您的“Shiv”)不可修改。
您将此类字符串文字的地址分配给指针,然后尝试通过取消引用指针值来更改字符串文字的内容。这是一个很大的禁忌。
将 str 声明为数组:
这会将 str 创建为 5 个字符的数组,并将字符“S”、“h”、“i”、“v”和“\0”复制到 str[ 0]、str[1]、...、str[4]。
str
每个元素中的值都是可修改的。当我想使用指向字符串文字的指针时,我通常将其声明为 const。这样,当我的代码想要更改字符串文字的内容时,编译器可以通过发出消息来帮助我
想象一下您可以对整数执行相同的操作。
引自标准:
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.
Declare str as an array instead:
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.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 literalImagine you could do the same with integers.
Quote from the Standard:
char *str 是指向字符块(字符串)的指针/引用。但它位于内存块中的某个位置,因此您不能像这样分配它。
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.
有趣的是我从来没有注意到这一点。我能够在 VS2008 C++ 中复制这种情况。
通常,对常量进行就地修改是一个坏主意。
无论如何,这篇文章非常清楚地解释了这种情况。
Interesting that I've never noticed this. I was able to replicate this condition in 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.