1

「読み取り専用」文字列について読んでいるときに、以下のスニペットに出くわしました。

#include<stdio.h>
main()
{
    char *foo = "some string";
    char *bar = "some string";
    printf("%d %d\n",foo,bar);
}

私が理解したのは、 foo と bar の両方が同じアドレスを出力するということですが、バックグラウンドで実際に何が起こっているのか理解できません。つまり、文字列が同じ場合は同じアドレスが返されますが、変更すると文字列アドレスが異なります。

4

2 に答える 2

7

ここに画像の説明を入力

foobarどちらも同じ住所を出力します

実際、標準によれば、それらは同じアドレスを持つ必要はなく、指定されていません。しかし実際には、ほとんどのコンパイラは同じアドレスを持つ同一の文字列リテラルを作成します。

文字列リテラルを変更することはできません。異なる文字列リテラルを使用していると思います。その場合、文字列が異なるアドレスを保持することは明らかです。

C11 6.4.5 文字列リテラル

これらの配列の要素が適切な値を持っている場合、これらの配列が異なるかどうかは指定されていません。プログラムがそのような配列を変更しようとした場合、動作は未定義です。

ここに画像の説明を入力

于 2013-10-18T06:05:34.293 に答える
1

でコードをビルドします

gcc yourcode.c -S -o yourcode.S

    .file   "main.c"
    .section    .rodata
.LC0:
    .string "some string"
.LC1:
    .string "%d %d\n"
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $16, %rsp
    movq    $.LC0, -16(%rbp)
    movq    $.LC0, -8(%rbp)
    movl    $.LC1, %eax
    movq    -8(%rbp), %rdx
    movq    -16(%rbp), %rcx
    movq    %rcx, %rsi
    movq    %rax, %rdi
    movl    $0, %eax
    call    printf
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu/Linaro 4.6.3-10ubuntu1) 4.6.3 20120918 (prerelease)"
    .section    .note.GNU-stack,"",@progbits

[char * foo] と [char *bar] は同じアドレスを指しています。この場合、「一部の文字列」は変更できません。これにより、実行時例外が発生します。

于 2013-10-18T06:04:07.543 に答える