我是编写C代码的新手,我确信在最基本的层面上我有些不对劲。我正在运行一个小代码来获取文件的属性,下面的函数返回这些属性。 char * path将包含类似“/ home / etc / bin”的内容
/* copy the attributes into a character pointer */
unsigned char * copyAttributes (char *path)
{
struct stat buf;
stat (path, &buf);
int nMalloc = sizeof(dev_t) + sizeof(ino_t) + sizeof(mode_t)+ sizeof(nlink_t)+ sizeof(uid_t)+ sizeof(gid_t)+ sizeof(dev_t)+ sizeof(off_t)+ sizeof(blksize_t)+ sizeof(blkcnt_t)+ sizeof(time_t)+ sizeof(time_t)+ sizeof(time_t)+ 1;
char *pathForStatBuff = malloc(nMalloc);
printf("%d\n",nMalloc);
unsigned long base = 0;
memcpy(pathForStatBuff + base,&buf.st_dev,sizeof(dev_t));
base = base + sizeof(dev_t);
memcpy(pathForStatBuff + base,&buf.st_ino,sizeof(ino_t));
base = base + sizeof(ino_t);
memcpy(pathForStatBuff + base,&buf.st_mode,sizeof(mode_t));
base = base + sizeof(mode_t);
memcpy(pathForStatBuff + base,&buf.st_nlink,sizeof(nlink_t));
base = base + sizeof(nlink_t);
memcpy(pathForStatBuff + base,&buf.st_uid,sizeof(uid_t));
base = base + sizeof(uid_t);
memcpy(pathForStatBuff + base,&buf.st_gid,sizeof(gid_t));
base = base + sizeof(gid_t);
memcpy(pathForStatBuff + base,&buf.st_rdev,sizeof(dev_t));
base = base + sizeof(dev_t);
memcpy(pathForStatBuff + base,&buf.st_size,sizeof(off_t));
base = base + sizeof(off_t);
memcpy(pathForStatBuff + base,&buf.st_blksize,sizeof(blksize_t));
base = base + sizeof(blksize_t);
memcpy(pathForStatBuff + base,&buf.st_blocks,sizeof(blkcnt_t));
base = base + sizeof(blkcnt_t);
memcpy(pathForStatBuff + base,&buf.st_atime,sizeof(time_t));
base = base + sizeof(time_t);
memcpy(pathForStatBuff + base,&buf.st_mtime,sizeof(time_t));
base = base + sizeof(time_t);
memcpy(pathForStatBuff + base,&buf.st_ctime,sizeof(time_t));
base = base + sizeof(time_t);
printf("Printing pathForStatBuff = %s\n",pathForStatBuff);
return pathForStatBuff;
}
打印pathForStatBuff = p 53 打印pathForStatBuff = p 53 打印pathForStatBuff = p 53 打印pathForStatBuff = p 53 打印pathForStatBuff = p 53 打印pathForStatBuff = p 53 打印pathForStatBuff = p 53 打印pathForStatBuff = p 53 打印pathForStatBuff = p 53 打印pathForStatBuff = p 53 打印pathForStatBuff = p
这是我总是得到的输出,我似乎无法弄清楚我做错了什么。你们可以指导一下这可能是什么。感谢。
答案 0 :(得分:3)
您正在尝试将二进制数据用作字符串。在C字符串中以零结尾,这意味着如果一个成员为零,那么当您将其复制到缓冲区时,它将标记字符串的结尾。
如果您想将所有数据转换为字符串,您应该使用例如snprintf
代替:
char buffer[128];
snprintf(buffer, sizeof(buffer), "%d %d %d",
buf.st_dev, buf.st_ino, buf.st_mode);
有关此功能的详细信息,请参阅snprintf
的手册页。
(在我的例子中,我只使用了结构的三个成员,添加了你需要的所有内容。)
答案 1 :(得分:3)
你正在复制没有变换的数据,所以如果buf.st_dev的最低有效字节为0(我假设小端),你最终会得到一个空字符串从你的例子来看,LSB看起来总是'p'(113)。你可以尝试使用一个函数,你给它提供字符串及其长度,并以十六进制打印,这样你就可以看到数据。你需要记住数字和它的十进制表示之间的差异,数字231与字符串“231”没有相似之处 否则你可以做类似的事情:
sprintf(pathForStatBuf, "Dev: %d\nIno: %d\n....", buf.st_dev, buf.st_ino, ...);
缺点是缓冲区大小不容易定义。
我猜你只是为了了解stat和stuff,所以你可以只分配一个大字符串(2048个字符左右),你应该保持在界限内。
答案 2 :(得分:1)
您正在将数据复制到内存块中。唯一的问题是你不能使用printf
和%s
来显示结果,因为它不是一个以空字符结尾的字符串(或任何类型的字符串)。
如果要打印出内存块的内容以进行调试,可以用十六进制打印:
{
int i;
printf("Printing pathForStatBuff = { ");
for (i = 0; i < sizeof nMalloc; i++)
printf("%#.2x ", (unsigned char)pathForStatBuff[i]);
printf("}\n");
}
答案 3 :(得分:0)
乍一看,代码:
int nMalloc = sizeof(dev_t) + sizeof(ino_t) + sizeof(mode_t)+ ...
与
完全相同int nMalloc = sizeof(struct stat);
编辑:警告 - caf指出
int nMalloc = sizeof(dev_t) + sizeof(ino_t) + ...
不必然与int nMalloc = sizeof(struct stat);
struct stat
中的字段可能具有对齐约束,这会导致字段之间出现“洞”或填充。可能还有未记录的字段。因此struct stat可能大于其已发布字段的总和。
这很容易检查。
if (nMalloc != sizeof(struct stat)) { fprintf(stderr, "...\n");
但将来可能会发生变化,因此您的原件更加强大。
根据caf的主张,这也不一定相同:
unsigned long base = 0;
memcpy(pathForStatBuff + base,&buf.st_dev,sizeof(dev_t));
base = base + sizeof(dev_t);
...
memcpy(pathForStatBuff + base,&buf.st_ctime,sizeof(time_t));
base = base + sizeof(time_t);
于:
memcpy(pathForStatBuff, &buf, sizeof(struct stat));
但尺寸测试会检测到。
因此,对新结构的字段赋值将允许您控制所需的字段,它们的顺序以及布局的某些方面(相同的编译器/相同平台)。
如果首选memcpy,请查看mempcpy。它就像memcpy,但返回指向最后一个字节后面的字节的指针,所以你不需要这样做:
p = memcpy(pathForStatBuf + base, ...
base = base + sizeof(...)
...
base = base + sizeof(...)
p = memcpy(pathForStatBuf + base, ...
base = base + sizeof(...)
但是有一个额外的指针并执行
p = memcpy(p, ...
p = memcpy(p, ...
您想获得可打印的表格吗?如果是这种情况,则需要使用sprintf,printf或fprintf。在您学习的过程中,我会将所有memcpy转换为printf("..., buf....field ...);
并立即查看,这比第一次获取字符串更容易。