参考下面的代码,我可以用这种方式将数据插入到结构的成员中。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct user {
int id;
char username[20];
char password[20];
};
int main(void) {
struct user *p;
p = malloc(sizeof(struct user));
p->id = 27;
strcpy(p->username, "roberto");
strcpy(p->password, "P4_4t4r");
printf("Id = %d\n", p->id);
printf("Username = %s\n", p->username);
printf("Password = %s\n", p->password);
return 0;
}
上面提到的程序就可以用了。现在,我想尝试使用指针运算,既可以用于赋值,也可以用于显示结构成员,我想我可以这样做。
#include <stdlib.h>
#include <stdio.h>
struct user {
int id;
char username[20];
char password[20];
};
int main(void) {
struct user *p;
p = malloc(sizeof(struct user));
*(int*)p = 27; // id = 27
p += 4; // int is 4 bytes, so let's move 4 bytes ...
*(char*)p = 'r';
*(char*)++p = 'o';
*(char*)++p = 'b';
*(char*)++p = 'e';
*(char*)++p = 'r';
*(char*)++p = 't';
*(char*)++p = 'o';
*(char*)++p = '\0';
p += 13;
*(char*)p = 'P';
*(char*)++p = '4';
*(char*)++p = '_';
*(char*)++p = '4';
*(char*)++p = 't';
*(char*)++p = '4';
*(char*)++p = 'r';
*(char*)++p = '\0';
p -= 31; // I put the pointer back to the first byte of the memory block
// Output
printf("Id = ");
printf("%d\n", *(int*)p);
p += 4;
printf("Username = ");
printf("%c", *(char*)p); // r
printf("%c", *(char*)++p); // o
printf("%c", *(char*)++p); // b
printf("%c", *(char*)++p); // e
printf("%c", *(char*)++p); // r
printf("%c", *(char*)++p); // t
printf("%c\n", *(char*)++p); // o
++p; // \0
p += 13;
printf("Password = ");
printf("%c", *(char*)p); // P
printf("%c", *(char*)++p); // 4
printf("%c", *(char*)++p); // _
printf("%c", *(char*)++p); // 4
printf("%c", *(char*)++p); // t
printf("%c", *(char*)++p); // 4
printf("%c\n", *(char*)++p); // r
++p; // \0
printf("\n");
p -= 31; // I put the pointer back to the first byte of the memory block
return 0;
}
我从两个来源的比较中意识到,右箭头选择(->)运算符非常有用。现在我想用指针算术将值赋给结构成员,然后用右箭头选择(->)运算符显示其内容,就像这样。
#include <stdlib.h>
#include <stdio.h>
struct user {
int id;
char username[20];
char password[20];
};
int main(void) {
struct user *p;
p = malloc(sizeof(struct user));
*(int*)p = 27;
p += 4;
*(char*)p = 'r';
*(char*)++p = 'o';
*(char*)++p = 'b';
*(char*)++p = 'e';
*(char*)++p = 'r';
*(char*)++p = 't';
*(char*)++p = 'o';
*(char*)++p = '\0';
p += 13;
*(char*)p = 'P';
*(char*)++p = '4';
*(char*)++p = '_';
*(char*)++p = '4';
*(char*)++p = 't';
*(char*)++p = '4';
*(char*)++p = 'r';
*(char*)++p = '\0';
p -= 31;
printf("Id = %d\n", p->id);
printf("Username = %s\n", p->username);
printf("Password = %s\n", p->password);
return 0;
}
但在后一种情况下,我得到了这样的结果。
Id = 27
Username =
Password =
谁能告诉我我错在哪里?
对一个结构的指针进行递增,会将其移动到结构的末端。
想象一个数组,其中每个元素是一个 struct user
. 如果 p
被宣布为 struct user *p
并指向该数组的起点。p += 4
将使其指向第五个要素(a struct user
)的数组中。
这意味着,当你在执行
*(char*)p = 'r';
*(char*)++p = 'o';
...
你已经超出了你分配的结构体的范围。
如果你想让指针按较小类型的大小递增,你需要首先将其投向该类型的指针。
unsigned char *byteptr = (unsigned char *)p;
然后使用 byteptr
来执行你的写入。
另一个隐藏的问题是,编译器和硬件架构的不同组合会导致不同的 排列要求. 这意味着编译器可能会在结构字段之间插入padding。
使用指针运算来计算结构字段的指针是个坏主意,因为你需要知道这些填充物是什么。你最好的办法是直接使用 ->
(在结构指针上)或 .
(在一个结构值上)。
不过你在这里做的是一个很好的学习练习。你可能应该使用 strncpy
而不是 strcpy
.