是什么让字符 * 成为字符数组

What makes a char * an array of chars?

本文关键字:字符 数组 是什么      更新时间:2023-10-16

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

int * i = &someint;

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

但是,当你这样做时

char * str = "somestring";

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

不,字符串文字"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 程序集时,给我们(删除了不相关的 cruft(:

.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 字符结尾的字符数组。

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

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
int * i = &someint;

除了其他评论,一般来说,我们可以说它是指向大小位置(int(的指针。因此,当我们访问"i"内部的值时。即 *i,检索 sizeof(int( 内存位置。此外,算术计算以相同的方式完成。即,递增指针 i+1 , 递增 + sizeof (int(。因此,检索到的数据的大小取决于变量的"数据类型"。

您使用的"通常"一词是这里问题的重要组成部分。

我认为可能使这种混乱的部分原因是许多需要char *的函数正在寻找 c 样式字符串(即以 null 结尾的字符数组(。这就是他们想要的。你可以编写一个只看字符的函数。

类似地,您可以编写一个函数,该函数采用 int* 并将其视为以 null 结尾的数组,这并不常见。这是有充分理由的,因为如果您想要值 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 样式字符串传递大小代替。 整数数组通常不以 null 结尾,但可以终止。归结为"正常"。

正如

人们所说str不是一个数组,而只是一个指向字符的指针("某物"的第一个,所以s(。然而,有 2 种语法糖

1-"something"初始化包含所有字符的内存块,并在末尾添加。所以

char *str = "something";

是合法糖

char *str = {'s', 'o', 'm', 'e', 't', 'h', 'i', 'n', 'g', ''};
              ^                                          ^^^^^
              |
              +- str

所以从技术上讲str,是 10 个字符长而不是 9 个字符。(请注意,str仅指向

阿拉伯数字-

str[5] 

是合法糖

*(str + 5)      

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