什么使char *成为一系列字符?

时间:2011-12-12 04:47:29

标签: c++ c arrays pointers char

通常,如果您执行以下操作:

int * i = &someint;

它只是一个指向变量的指针。

但是,当你这样做时

char * str = "somestring";

它会自动将其转换为数组。它是执行此操作的指针,还是初始化语法的语法糖?

6 个答案:

答案 0 :(得分:14)

不,字符串文字"somestring" 已经一个字符数组,几乎可以肯定是由编译器创建的。

该声明正在做的是将str设置为指向第一个字符。如果您要查看底层的汇编程序代码,它可能看起来像:

str314159:  db   "somestring", 0  ; all string literals here.
: :         : :
            load r0, str314159    ; get address of string
            stor r0, -24[sp]      ; store it into local var str.

在很多情况下,数组会衰减到指向该数组的第一个元素的指针(有一些有限的例外,例如在执行sizeof时)。


举例来说,以下C代码:

#include <stdio.h>

int main (void) {
    char *somestr = "Hello";
    puts (somestr);
    return 0;
}

使用gcc -S编译生成x86程序集时,会给我们(删除无关紧要的内容):

.LC0:
    .string    "Hello"
    .text
.globl main
    .type      main, @function
main:
    pushl      %ebp                ; Standard set up of stack frame,
    movl       %esp, %ebp          ;   aligning and making
    andl       $-16, %esp          ;   room for
    subl       $32, %esp           ;   local variables.

    movl       $.LC0, 28(%esp)     ; Load address of string in to somestr.

    movl       28(%esp), %eax      ; Call puts with that variable.
    movl       %eax, (%esp)
    call       puts

    movl       $0, %eax            ; Set return code.

    leave                          ; Tear down stack frame and return.
    ret

您可以看到第一个字符.LC0的地址确实已加载到somestr变量中。而且,虽然它可能不会立即明显.string确实会创建一个由NUL字符终止的字符数组。

答案 1 :(得分:3)

它不是指向变量的指针。它是指向内存中某个位置的指针。您正在创建一个变量并将其存储在某个内存位置,然后将指针指向该位置。它适用于数组的原因是因为数组的元素背靠背存储在内存中。指针指向数组的开头。

答案 2 :(得分:2)

char * str 

是指向角色的指针。将字符串分配给字符指针时,它指向字符串的第一个字符,而不是整个字符串。如果指针递增,您可以看到它指向字符串中的第二个字符。当您打印字符指针时,cout对象打印该字符并继续打印字符,直到看到空字符(\ 0)。

#include <iostream>
using namespace std;

int main()
{
    char *s = "something";
    cout << "before :" << s << endl;
    s++;
    cout << "after :" << s << endl;
}

此程序打印:

~/cpp: ./stringarray
before :something
after :omething

答案 3 :(得分:0)

int * i = &someint;

除了其他注释之外,通常我们可以说它是指向size(int)位置的指针。所以,当我们访问'i'里面的价值时。 ie * i,检索sizeof(int)内存位置。此外,算术计算以相同的方式完成。即,递增指针i + 1,递增+ sizeof(int)。因此,检索数据的大小取决于变量的“数据类型”。

答案 4 :(得分:0)

你使用“通常”这个词在这里是一个很大的问题。

我认为可能导致这种混乱的部分原因是许多函数char *正在寻找一个c样式字符串(即空终止字符数组)。这就是他们想要的。你可以编写一个只看着角色的函数。

类似地,你可以编写一个带有int *的函数,并将其视为一个空终止数组,它只是不常见。并且有充分的理由,因为如果你想要值0怎么办?在c样式字符串中(用于显示而不是二进制数据),你永远不会想要0。

#include <iostream>

const int b_in_data[]={50,60,70,80,0};

int Display (const int * a)
{
  while ( *a != 0){
    std::cout << *a; ++a;
  }
}    

int main()
{

 int a[]={20,30,40,0};

 // or more like char* = something because compiler is making string literal for you 
 // probably somewhere in data section and replacing it with its address
 const int *b = b_in_data;

 Display(a);
 Display(b);
 return 0;
}

C样式字符串只是选择终止而不是传递大小,而B样式字符串则传递大小。 int数组通常不是空终止但可以是。归结为“正常”。

答案 5 :(得分:0)

正如人们所说str不是一个数组而只是一个指向char的指针(第一个是“某事”,所以s)。然而,有2种语法糖

1- "something"使用所有字符初始化一块内存,**并在末尾添加\0。 所以

char *str = "something";

的语法糖
char *str = {'s', 'o', 'm', 'e', 't', 'h', 'i', 'n', 'g', '\0'};
              ^                                          ^^^^^
              |
              +- str

技术上str,长度不超过10个字符。(注意str仅指向

2 -

str[5] 

的语法糖
*(str + 5)      

然后,有一个约定,大多数(不是全部)C函数处理字符串,期望最后一个字符\0(知道它结束的位置)。其他一些(见strncpy,需要长度作为额外的参数,可以添加或不添加'\ 0'。