为什么 *(str+i) = *(str +j) 在这里不起作用?

发布于 2024-08-07 20:45:08 字数 540 浏览 4 评论 0原文


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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

人海汹涌 2024-08-14 20:45:08

当您使用 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.

深空失忆 2024-08-14 20:45:08

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.

谜泪 2024-08-14 20:45:08
char *str = "Shiv";

这应该是:

const char *str = "Shiv";

现在你会遇到一个错误;)

char *str = "Shiv";

This should be :

const char *str = "Shiv";

And now you'll have an error ;)

桃扇骨 2024-08-14 20:45:08

尝试

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;
}

一下。这将使您在使用指针时读/写内存。使用 [] 表示法直接在堆栈中分配空间,但使用 const 指针则不会。

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.

旧人九事 2024-08-14 20:45:08

在 C 和 C++ 中,字符串文字都是不可修改的对象。尝试修改字符串文字总是会导致未定义的行为。这正是您在收到

char *str = "Shiv";

变体“总线错误”时所观察到的情况。在这种情况下,您的“反向”函数将尝试修改字符串文字。因此,行为是未定义的。

char str[] = "Shiv";

变体将在可修改数组“str”中创建字符串文字的副本,然后“reverse”将对该副本进行操作。这会工作得很好。

PS 不要创建指向字符串文字的非 const 限定指针。你的第一个变体应该是

const char *str = "Shiv";

(注意额外的“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

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.

P.S. Don't create non-const-qualified pointers to string literals. You first variant should have been

const char *str = "Shiv";

(note the extra 'const').

椒妓 2024-08-14 20:45:08

字符串文字(您的“Shiv”)不可修改。
您将此类字符串文字的地址分配给指针,然后尝试通过取消引用指针值来更改字符串文字的内容。这是一个很大的禁忌。

将 str 声明为数组:

char str[] = "Shiv";

这会将 str 创建为 5 个字符的数组,并将字符“S”、“h”、“i”、“v”和“\0”复制到 str[ 0]、str[1]、...、str[4]。 str 每个元素中的值都是可修改的。

当我想使用指向字符串文字的指针时,我通常将其声明为 const。这样,当我的代码想要更改字符串文字的内容时,编译器可以通过发出消息来帮助我

const char *str = "Shiv";

想象一下您可以对整数执行相同的操作。

/* 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?  :)  */

引自标准:

6.4.5 字符串文字
...
6 ...如果程序尝试修改这样的数组[字符串文字],则行为未定义。

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:

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.

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 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.

十年不长 2024-08-14 20:45:08

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.

迷乱花海 2024-08-14 20:45:08

有趣的是我从来没有注意到这一点。我能够在 VS2008 C++ 中复制这种情况。

通常,对常量进行就地修改是一个坏主意。

无论如何,这篇文章非常清楚地解释了这种情况。

第一个 (char[]) 是您可以编辑的本地数据
(因为数组是本地数据)。

第二个 (char *) 是一个本地指针
全局、静态(常量)数据。你
不允许修改常量
数据。

如果你有GNU C,你可以编译
使用 -fwritable-strings 来保留
生成全局字符串
常量,但不建议这样做。

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.

The first (char[]) is local data you can edit
(since the array is local data).

The second (char *) is a local pointer to
global, static (constant) data. You
are not allowed to modify constant
data.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文