我是C的新手,请原谅我这个问题是否微不足道。我试图扭转一个字符串,在
我的情况是字母a,b,c,d。我将字符放在char *数组中,并声明一个缓冲区
它将以相反的顺序保存字符,d,c,b,a。我用它来实现这个结果
指针算术,但据我所知,char *数组中的每个元素都是4个字节,所以当我执行以下操作时:buffer[i] = *(char**)letters + 4;
我应该指向
数组中的第二个元素。而不是指向第二个元素,它指向第三个元素。经过进一步检查后,我认为如果我将基指针增加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");
}
答案 0 :(得分:3)
你没有制作一个字符数组:你正在创建一个字符字符串的数组 - 即一个指向字符数组的指针数组。当然,我不打算为你重写整个程序,但我会从主数据结构的两个可能的正确声明开始:
char letters[] = {'a','b','c','d, 0};
char * letters = "abcd";
其中任何一个都声明一个包含五个字符的数组:a,b,c,d后跟0,即C中字符串的传统结尾。
答案 1 :(得分:2)
另一件事:使用语言告诉你,而不是对事物的大小做出假设。例如:
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的指针数组(恰好是以空字符结尾的C风格字符串),它用4个元素初始化。letters
类似,buffer
是一个包含4个指向char但未初始化的数组的数组。即使在printf()
语句中,您实际上并没有在任何地方处理单个字符:%s
说明符表示该参数是以空字符结尾的字符串。相反,你正在处理字符串(也就是指向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");
}
顺便说一下,这是家庭作业吗?
答案 2 :(得分:0)
这是运营商优先的情况。当您使用buffer[i] = *(char**)letters + add;
时,在*
之前执行演员之前的+
,使此代码等同于(*(char**)letters) + add;
。第一部分相当于数组中第一个元素的地址,即字符串“a”。由于使用字符串常量会自动添加空字节,因此指向'a\0'
。碰巧编译器将所有四个字符串紧跟在内存中,所以如果你超过该字符串的末尾,则会流入下一个字符串。当您添加到指针时,您正在浏览此字符数组:'a\0b\0c\0d\0'
。请注意,每个字符在最后一个字符后是2个字节。因为这只是因为编译器将4个字符串直接放在一起,所以你永远不应该依赖它(如果你试图重新反转你的其他字符串,它甚至都不会起作用)。相反,您需要放入括号以确保在取消引用之前添加,并使用4字节指针大小。 (当然,正如Nicholas所指出的,你不应该假设任何东西的大小。使用sizeof来代替指针的大小。)
buffer[i] = *((char**)letters + add);
答案 3 :(得分:0)
char *letters[] = {"a","b","c","d"};
我认为你没有正确地获得指针算法。 letters
是一个指针数组,当递增1时,转到下一行。
letters + 1 ; // Go to starting location of 2 row, i.e., &"b"
char *letters[] = { "abc" , "def" } ;
(letters + 1) ; // Point to the second row's first element, i.e., &"d"
*((*letters) + 1) ; // Get the second element of the first row. i.e., "b"