我进行了一次简短的采访,问题是这样的:在地址0xaa55
设置一个整数值为0x*****9
。
我唯一注意到的是给定的地址在字边界上没有对齐。因此,将int *p
设置为该地址不起作用。那么它只是使用unsigned char *p
以字节方式分配值吗?这是面试问题的重点吗?在现实生活中没有必要这样做,是吗?
答案 0 :(得分:7)
你需要回答面试官的一些辅助问题:
int
的字节大小是多少?有人可能正在考虑以快速而肮脏的方式编组数据。
您说得对,一个基本过程是通过初始化为相关地址的char *
或unsigned char *
来写入字节。我的子公司问题1和2的答案确定了使用的确切机制,但对于小端格式的2字节int
,您可以使用:
unsigned char *p = 0x*****9; // Copied from question!
unsigned int v = 0xAA55;
*p++ = v & 0xFF;
v >>= 8;
*p = v & 0xFF;
您可以轻松地推广到4字节或8字节整数;处理大端整数更加繁琐。
我收集了一些计时代码,看看相对成本是多少。在MacBook Pro(2.3 GHz Intel Core i7,16 GiB 1333 MHz DDR3 RAM,Mac OS X 10.7.5,自制GCC 4.7.1)上进行测试,我得到了以下非优化代码的时间:
Aligned: 0.238420
Marshalled: 0.931727
Unaligned: 0.243081
Memcopy: 1.047383
Aligned: 0.239070
Marshalled: 0.931718
Unaligned: 0.242505
Memcopy: 1.060336
Aligned: 0.239915
Marshalled: 0.934913
Unaligned: 0.242374
Memcopy: 1.049218
当使用优化进行编译时,即使没有-DUSE_UNALIGNED
,我也会出现分段错误 - 这让我感到困惑。调试并不容易;似乎有很多积极的内联优化,这意味着调试器无法打印变量。
代码如下。 Clock
类型和time.h
标题(以及timer.c
来源)未显示,但可以根据要求提供(请参阅我的个人资料)。它们在大多数平台上提供高分辨率计时(Windows最不稳定)。
#include <string.h>
#include <stdio.h>
#include "timer.h"
static int array[100000];
enum { ARRAY_SIZE = sizeof(array) / sizeof(array[0]) };
static int repcount = 1000;
static void uac_aligned(int value)
{
int *base = array;
for (int i = 0; i < repcount; i++)
{
for (int j = 0; j < ARRAY_SIZE - 2; j++)
base[j] = value;
}
}
static void uac_marshalled(int value)
{
for (int i = 0; i < repcount; i++)
{
char *base = (char *)array + 1;
for (int j = 0; j < ARRAY_SIZE - 2; j++)
{
*base++ = value & 0xFF;
value >>= 8;
*base++ = value & 0xFF;
value >>= 8;
*base++ = value & 0xFF;
value >>= 8;
*base = value & 0xFF;
value >>= 8;
}
}
}
#ifdef USE_UNALIGNED
static void uac_unaligned(int value)
{
int *base = (int *)((char *)array + 1);
for (int i = 0; i < repcount; i++)
{
for (int j = 0; j < ARRAY_SIZE - 2; j++)
base[j] = value;
}
}
#endif /* USE_UNALIGNED */
static void uac_memcpy(int value)
{
for (int i = 0; i < repcount; i++)
{
char *base = (char *)array + 1;
for (int j = 0; j < ARRAY_SIZE - 2; j++)
{
memcpy(base, &value, sizeof(int));
base += sizeof(int);
}
}
}
static void time_it(int value, const char *tag, void (*function)(int value))
{
Clock c;
char buffer[32];
clk_init(&c);
clk_start(&c);
(*function)(value);
clk_stop(&c);
printf("%-12s %12s\n", tag, clk_elapsed_us(&c, buffer, sizeof(buffer)));
}
int main(void)
{
int value = 0xAA55;
for (int i = 0; i < 3; i++)
{
time_it(value, "Aligned:", uac_aligned);
time_it(value, "Marshalled:", uac_marshalled);
#ifdef USE_UNALIGNED
time_it(value, "Unaligned:", uac_unaligned);
#endif /* USE_UNALIGNED */
time_it(value, "Memcopy:", uac_memcpy);
}
return(0);
}
答案 1 :(得分:3)
memcpy((void *)0x23456789, &(int){0xaa55}, sizeof(int));
答案 2 :(得分:0)
是的,您可能需要在现实生活中处理未对齐的多字节值。想象一下,您的设备与其他设备交换数据。例如,该数据可以是通过网络发送的消息结构或保存到磁盘的文件结构。该数据的格式可能是预定义的,不受您的控制。并且数据结构的定义可能无法解释设备的对齐(甚至字节顺序)限制。在这些情况下,访问这些未对齐的多字节值时需要注意。