为什么我的char*数组中的元素是两个字节而不是四个字节

为什么我的char*数组中的元素是两个字节而不是四个字节,c,C,我是C语言的新手,所以如果这个问题很琐碎,请原谅我。我正在尝试反转一个字符串,在 我的箱子是字母a、b、c、d。我将字符放在char*数组中,并声明一个缓冲区 它将按相反的顺序保存字符,d,c,b,a。我使用 指针算法,但据我所知,char*数组中的每个元素都是4字节,因此当我执行以下操作时:buffer[I]=*(char**)字母+4我应该指向 数组中的第二个元素。它不是指向第二个元素,而是指向第三个元素。经过进一步的检查,我认为如果我将基指针增加2 每次我都会得到想要的结果。这是否意味着数

我是C语言的新手,所以如果这个问题很琐碎,请原谅我。我正在尝试反转一个字符串,在 我的箱子是字母a、b、c、d。我将字符放在char*数组中,并声明一个缓冲区 它将按相反的顺序保存字符,d,c,b,a。我使用 指针算法,但据我所知,char*数组中的每个元素都是4字节,因此当我执行以下操作时:
buffer[I]=*(char**)字母+4我应该指向
数组中的第二个元素。它不是指向第二个元素,而是指向第三个元素。经过进一步的检查,我认为如果我将基指针增加2
每次我都会得到想要的结果。这是否意味着数组中的每个元素
是2字节而不是4字节吗?以下是我的代码的其余部分:

#include <stdio.h>

int main(void)
{

  char *letters[] = {"a","b","c","d"};
  char *buffer[4];
  int i, add = 6;

  for( i = 0 ; i < 4 ; i++ )
  {
    buffer[i] = *(char**)letters + add;
    add -= 2;
  }

  printf("The alphabet: ");

  for(i = 0; i < 4; i++)
  {
    printf("%s",letters[i]);
  }

  printf("\n");

  printf("The alphabet in reverse: ");

  for(i = 0; i < 4; i++)
  {
    printf("%s",buffer[i]);
  }

  printf("\n");

}
#包括
内部主(空)
{
字符*字母[]={“a”、“b”、“c”、“d”};
字符*缓冲区[4];
整数i,相加=6;
对于(i=0;i<4;i++)
{
缓冲区[i]=*(字符**)字母+加法;
加-=2;
}
printf(“字母表:”);
对于(i=0;i<4;i++)
{
printf(“%s”,字母[i]);
}
printf(“\n”);
printf(“相反的字母:”);
对于(i=0;i<4;i++)
{
printf(“%s”,缓冲区[i]);
}
printf(“\n”);
}

您没有创建字符数组:您创建的是字符串数组,即指向字符数组的指针数组。当然,我不会为您重写整个程序,但我将首先为您的主数据结构提供两种可能的正确声明:

char letters[] = {'a','b','c','d, 0};

char * letters = "abcd";

其中任何一个都声明了一个由五个字符组成的数组:a、b、c、d后跟0,这是c中字符串的传统结尾。

您不是在创建一个字符数组:您正在创建一个字符串数组,即指向字符数组的指针数组。当然,我不会为您重写整个程序,但我将首先为您的主数据结构提供两种可能的正确声明:

char letters[] = {'a','b','c','d, 0};

char * letters = "abcd";

这其中任何一个都声明了一个由五个字符组成的数组:a、b、c、d后跟0,这是c中字符串的传统结尾。

另一件事:与其对事物的大小进行假设,不如使用语言来告诉您。例如:

char   *my_array[]            = { "foo" , "bar" , "baz" , "bat" , } ;
// the size of an element of my_array
size_t  my_array_element_size = sizeof(my_array[0]) ;
size_t  alt_element_size      = size(*my_array) ; // arrays are pointers under the hood
// the number of elements in my_array
size_t  my_array_element_cnt  = sizeof(my_array) / sizeof(*myarray ;
// the size of a char
size_t  char_size             = sizeof(*(my_array[0])) ; // size of a char
另一件事:了解您的数据结构(如上所述)。您谈论的是字符,但您的数据结构谈论的是字符串。你的声明:

char *letters[] = {"a","b","c","d"};
char *buffer[4];
按如下方式进行分析:

  • letters
    是指向char的指针数组(恰好是以nul结尾的C样式字符串),它由4个元素初始化
  • 字母
    类似,
    缓冲区
    是一个由4个指向char的指针组成的数组,但未初始化
实际上,您没有在任何地方处理单个字符,即使在
printf()
语句中也是如此:
%s
说明符表示参数是以nul结尾的字符串。相反,您处理的是字符串(即指向
char
的指针)及其数组

更简单的方法:

#include <stdio.h>

int main(void)
{

  char   *letters[]  = { "a" , "b" , "c" , "d" , }    ;
  size_t  letter_cnt = size(letters)/sizeof(*letters) ;
  char   *buffer[sizeof(letters)/sizeof(*letters)]    ;

  for ( int i=0 , j=letter_cnt ; i < letter_cnt ; ++i )
  {
    buffer[--j] = letters[i] ;
  }

  printf("The alphabet: ");
  for( int i = 0 ; i < letter_cnt ; ++i )
  {
    printf("%s",letters[i]);
  }
  printf("\n");

  printf("The alphabet in reverse: ");
  for( int i=0 ; i < letter_cnt ; i++ )
  {
    printf("%s",buffer[i]);
  }
  printf("\n");

}
#包括
内部主(空)
{
字符*字母[]={“a”、“b”、“c”、“d”、};
大小字母=大小(字母)/sizeof(*字母);
字符*缓冲区[sizeof(字母)/sizeof(*字母)];
对于(int i=0,j=letter_cnt;i

顺便说一句,这是家庭作业吗?

另一件事:与其对事物的大小做出假设,不如用语言告诉你。例如:

char   *my_array[]            = { "foo" , "bar" , "baz" , "bat" , } ;
// the size of an element of my_array
size_t  my_array_element_size = sizeof(my_array[0]) ;
size_t  alt_element_size      = size(*my_array) ; // arrays are pointers under the hood
// the number of elements in my_array
size_t  my_array_element_cnt  = sizeof(my_array) / sizeof(*myarray ;
// the size of a char
size_t  char_size             = sizeof(*(my_array[0])) ; // size of a char
另一件事:了解您的数据结构(如上所述)。您谈论的是字符,但您的数据结构谈论的是字符串。你的声明:

char *letters[] = {"a","b","c","d"};
char *buffer[4];
按如下方式进行分析:

  • letters
    是指向char的指针数组(恰好是以nul结尾的C样式字符串),它由4个元素初始化
  • 字母
    类似,
    缓冲区
    是一个由4个指向char的指针组成的数组,但未初始化
实际上,您没有在任何地方处理单个字符,即使在
printf()
语句中也是如此:
%s
说明符表示参数是以nul结尾的字符串。相反,您处理的是字符串(即指向
char
的指针)及其数组

更简单的方法:

#include <stdio.h>

int main(void)
{

  char   *letters[]  = { "a" , "b" , "c" , "d" , }    ;
  size_t  letter_cnt = size(letters)/sizeof(*letters) ;
  char   *buffer[sizeof(letters)/sizeof(*letters)]    ;

  for ( int i=0 , j=letter_cnt ; i < letter_cnt ; ++i )
  {
    buffer[--j] = letters[i] ;
  }

  printf("The alphabet: ");
  for( int i = 0 ; i < letter_cnt ; ++i )
  {
    printf("%s",letters[i]);
  }
  printf("\n");

  printf("The alphabet in reverse: ");
  for( int i=0 ; i < letter_cnt ; i++ )
  {
    printf("%s",buffer[i]);
  }
  printf("\n");

}
#包括
内部主(空)
{
字符*字母[]={“a”、“b”、“c”、“d”、};
大小字母=大小(字母)/sizeof(*字母);
字符*缓冲区[sizeof(字母)/sizeof(*字母)];
对于(int i=0,j=letter_cnt;i

顺便说一句,这是作业吗?

这是运算符优先的情况。使用
buffer[i]=*(char**)字母+add时
,在转换之前的
*
+
之前执行,使此代码相当于
(*(char**)字母)+add。第一部分相当于数组中第一个元素的地址,字符串“a”。由于使用字符串常量会自动添加一个空字节,因此指向
'a\0'
。编译器恰好将所有四个字符串紧跟在一起放入内存中,因此,如果超过该字符串的末尾,则会流入下一个字符串。添加到指针时,您将在以下字符数组中移动:
'a\0b\0c\0d\0'
。请注意,每个字符在最后一个字符后有2个字节。因为这是唯一正确的,因为编译器直接放置了4个字符串