作为一项学术任务,我需要使用整数变量将char数组复制到char数组,以便在每次迭代中一次复制4个字符。我知道有专门的功能可以做到这一点,这只是运动的问题。我试过如下:
char source[SIZE];
//populate chars in source
char dest[SIZE];
for (int i = 0; i < (SIZE + 3) / 4; i++)
{
int number = *(int*)(source + 4 * i);
*(dest + 4 * i) = (int)number;
}
结果是只有每四个元素被正确复制,所以我想我用指针混合了一些东西。我该如何纠正?
答案 0 :(得分:2)
写作部分错了,你写信给
*(dest + 4 * i)
并且dest
是指向char
的指针,此表达式的类型仍为char
。 number
的强制转换需要不,它已经是int
。所以&#34;正确&#34;行将是:
*(int *)(dest + 4 * i) = number;
我写'#34;正确&#34;在引号中,因为根据标准C,不允许使用不同类型的别名指针。作为一个例外,char
指针可以为任何其他指针设置别名,但在这里你反过来,这绝不能保证按预期工作。
另请注意,您所执行的操作不必要地复杂,您可以将int *
替换为数组的开头,并将该指针递增1以获取下一个int
,或使用简单的索引器。它看起来很简单:
char source[SIZE];
//populate chars in source
char dest[SIZE];
int *srcptr = (int *)source;
int *dstptr = (int *)dst;
for (int i = 0; i < SIZE / sizeof(int); ++i)
{
dstptr[i] = srcptr[i];
}
请注意,这根本不是可移植的:它取决于某些属性,例如机器不需要int
的对齐,不使用任何填充位等。
最后,一个例子说明即使满足这些假设,这也可能出现问题,例如在x86
:
char source[SIZE];
char dest[SIZE];
source[0] = 'a';
dest[0] = 'b';
int *srcptr = (int *)source;
int *dstptr = (int *)dst;
for (int i = 0; i < SIZE / sizeof(int); ++i)
{
dstptr[i] = srcptr[i];
}
printf("%c\n", dest[0]); // <- might output 'b'
这是一个简单的愚蠢的示例,但积极优化的编译器可能确实优化了dest[0]
的最终读取,因为它已经知道&#34;从上面的行中它保存值'b'
。因为指向不同类型的指针不是允许来对数组进行别名,所以逻辑是,此程序中的任何内容都不可能是别名。在这个愚蠢的例子中并不那么明显,但是对于更复杂的程序,编译器可能根本没有办法确定指针是否相互别名,因此严格的别名规则使得决策更容易进行优化。
答案 1 :(得分:2)
由于这是一项学习任务,您应该提交一份说明,说明您要求实现的内容无法在C中完成而不会调用未定义的行为。
这至少导致未定义行为的原因之一是因为某些机器具有因类型而异的对齐限制。例如,一台机器可以允许在任何地址找到char,但要求32位整数位于可被4整除的地址。在这样的机器上,char* p = ...; *((uint32_t*)p)
可能导致对齐错误。
(即使在对32位整数没有对齐限制的机器上,读取未对齐的整数也可能比读取对齐的整数要慢。)
最好的情况是,您可以使用特定编译器的特定版本的特定设置来编写适用于特定计算机的代码。你正坐在定时炸弹上。
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// XXX Relies on undefined behaviour.
void* my_memcpy(void* dst, const void* src, size_t n) {
uint32_t* dst_uint32_ptr = (uint32_t*)dst;
const uint32_t* src_uint32_ptr = (const uint32_t*)src;
for (; n>4; n-=4) { *(dst_uint32_ptr++) = *(src_uint32_ptr++); }
char* dst_char_ptr = (char*)dst_uint32_ptr;
const char* src_char_ptr = (const char*)src_uint32_ptr;
while (n--) { *(dst_char_ptr++) = *(src_char_ptr++); }
return dst;
}
int main(void) {
const char* orig = "Hello, world.";
size_t len = strlen(orig)+1;
char* copy = malloc(len);
my_memcpy(copy, orig, len);
printf("%s\n", copy);
free(copy);
return 0;
}
输出:
$ gcc -Wall -Wextra -pedantic --std=c99 -o a a.c && a
Hello, world.
答案 2 :(得分:0)
你只是忘了施放目标指针
*(int *)(dest + 4 * i) = number;
这就是问题的原因,因为你只写了一个字节。