2017-10-04 88 views
0

恒定的是否定义:机制初始化数组的一个字符串用C

char arr_of_chars[] = "hello world"; 

创建一个常数字符阵列(空终止)在存储器中某处,然后该数组中的内容复制到arr_of_chars,或它是否直接将其分配给arr_of_chars

究竟是什么机制在这里工作?

+0

'你好world'是在系统中的某个地方放置空终止字符串。当变量被初始化时,字符串被复制到RAM中。 – tilz0R

+1

如果变量是全局变量或静态变量,那么初始化也是如此,并且在运行时不会执行复制。如果变量是自动的,那么初始化是动态的,并且在每次变量被实例化时执行。 –

+0

@TomKarzes我不相信。考虑这个:'const char a [] =“hello world”; char b [] =“hello world”;'。你有2个确切的值,即使它们是全局的或静态的,你在.rodata节中只会有一个'hello world'的存储器,特别是在嵌入式系统上。它将首先在运行时被复制到非const变量。 – tilz0R

回答

0

“...创建一个常数字符阵列(空终止)在存储器中某处,而且阵列然后复制的内容,以arr_of_chars”

事实上。字符串文字"hello world"存储在程序的.rodata部分的某处,除非编译器设法完全将其优化(取决于您的数组的范围)。从那里它被复制到你的数组中。

+0

它是''一般规则中唯一的例外,因为它复制字符串本身,而不是通常的指针:)。 –

+1

这里根本没有例外。这是一个初始化,而不是一个赋值。 –

+0

什么是'.rodata'? - ) –

0

这将在常量段中创建一个以NULL结尾的字符串hello world\0

在主函数中,这个字符串将被复制到字符数组中。

让我突出从汇编输出的几行,以clairfy这一点。

PUBLIC [email protected][email protected]@[email protected] 

这会创建一个公共令牌。

CONST SEGMENT 
[email protected][email protected]@[email protected] DB 'hello world', 00H 
CONST ENDS 

这将常量空终止的字符串分配给令牌。

lea rax, QWORD PTR arr_of_chars$[rbp] 
lea rcx, OFFSET FLAT:[email protected][email protected]@[email protected] 
mov rdi, rax  ; Set destination to stack location 
mov rsi, rcx  ; Set source to public token 
mov ecx, 12  ; Set counter to number of times to repeat 
rep movsb   ; Copy single byte from source to destination and increment locations 

这由字符建立源和目的地和副本字符的12倍,这是“世界你好”的长度和空终止。目标是堆栈中的一个位置,源代码是公共令牌。

+1

如何检查**一个**行为的具体实现回答这个问题? –

+0

@FelixPalmen - 你说得对。我发布的只是一个观察。但我不确定该标准是否定义了执行此操作的方法。但是,该操作是一个正在使用字符串文字初始化的数组。所以字符串文字必须存储在某个地方,并且必须在初始化过程中复制到数组中。 – Superman

+0

它**不是由标准指定的,这是我的观点;)不,不是绝对必须在某处存储字符串文字。这一切都取决于目标的二进制格式和编译器的决定,如果这个确切的字符串文字是** only **用于初始化这个变量,它*可以*是一个有效的决定来“消除”它并把初始化数据段中的数组 - 例如:) –

1

不是由C指定的是什么你问简而言之,C在抽象机及其观察行为方面指定的。在这种情况下,这意味着所有你知道的是从字符串文字初始化的数组变量arr_of_chars

在谈论段,复制等时,你已经在讨论C的具体实现以及它们在做什么。假设arr_of_chars位于文件范围内,并且给定了知道具有数据段的二进制文件的目标机器/系统,C编译器可以将初始化数组直接放入数据段 - 可观察行为与方法是运行时首先将字节复制到阵列中。

+0

没问题。如果字符串很短,另一种初始化的可能性是使用硬件寄存器或立即数,并且取决于char数组的用法,根本不在内存中表示它。 –

0

它是c中存储字符串的主题。

字符串可以被存储在以下方式,

  1. 字符串作为字符数组使用字符指针

当字符串被声明为字符数组

  • 字符串,将它们存储等的其它类型的例如,如果str []是一个自动变量,则字符串将存储在堆栈段中,如果它是全局或静态变量,则存储在数据段中。

    Ex。

    char str[] = "Hello_world"; 
    

    在存储使用字符指针串的情况下,它可以通过两种方式来完成,

    1. 在共享段只读字符串。

      Ex。

      char *str = "Hello_World"; 
      

    在上述线“程序hello_world”被存储在一个共享的只读位置,但指针STR被存储在读 - 写存储器。你可以改变str以指向别的东西,但不能改变当前的值。所以这种类型的字符串应该只在我们不想在程序的后续阶段修改字符串时使用。

    1. 在堆段中动态分配。

      char *str = NULL; 
      int size = 6; 
      
      str = (char *) malloc(sizeof(char)*size); 
      
      *(str+0) = 'H'; 
      *(str+1) = 'E'; 
      *(str+2) = 'L'; 
      *(str+3) = 'L'; 
      *(str+4) = 'O'; 
      *(str+5) = '\0';