为什么编译器会将此变量初始化为错误的值?这是对齐问题吗?

问题描述 投票:0回答:3

我正在使用嵌入式 C 编译器(ARM cortex-m3 芯片),它似乎将错误的值初始化为结构。 为什么会出现这种情况?如果是对齐问题,编译器不应该知道将 int32u 与 4 字节边界对齐吗?

注意:printf 只是将字节从串行端口中抛出。该芯片上没有 stdio.h 实现。

typedef struct
{
    int32u startTime; 
    int16u length;
    int32u offTime;
} Cycle;

Cycle cycle = 
{
    315618000, 
    1200,
    0
};


void init()
{
   printf("\r\nInitialized! Cycle Start: %d", cycle.startTime);

   cycle.startTime = 315618000;
   cycle.length = 1200;

   printf(" Cycle Start: %d", cycle.startTime);

}

输出: 已初始化!循环开始:631237200 循环开始:315618000

注意::这不是 printf 问题。 调试器也会验证内存中的值是否为 631237200。

c memory memory-alignment
3个回答
1
投票

在某些嵌入式系统中,静态初始化并未设置为自动发生。这违背了 C 规范,但有时就是这样。请注意,这对于 data 和 bss 段可能都是如此,即您可能会发现未初始化的静态变量也可能不会初始化为零。

不幸的是,这个问题的解决方案是特定于系统的。您可能会在编译器系统文档中找到一些内容,可以让您调用静态元素的初始化。


1
投票
[编辑]我在下面建议的 sizeof(int) == 2 可能不是问题,因为

" Cycle Start: %d", cycle.startTime 很容易打印出> 64k 的值。 我怀疑是填充问题。 但是关于 printf() 的较低建议适用,即使它们没有解释这个问题。


cycle
的初始化实际上会产生

cycle.startTime = 315618000

。  你的 int/unsigned 大小可能是 2,因此初始化溢出。  相反:
Cycle cycle = {
  315618000LU, 
  1200,
  0
  };

您的
printf()
还应该使用 uint32_t 的匹配格式说明符

#include <inttypes.h>
printf("Cycle Start: %" PRIu32 "\n", cycle.startTime);
printf("Length     : %" PRIu16 "\n", cycle.length);

您可能可以通过查看汇编代码来了解发生了什么。不知道你的编译器是不是GCC。如果是 -S 标志应该生成一个名为输入文件但带有 .s 扩展名的汇编文件。

0
投票
这样您应该能够查看分配给全局结构变量的值。

另一个可能出错的地方是 printf 函数。如果您没有使用像

int printf(const char *fmt, ...)

这样将其声明为可变参数函数的函数原型,那么调用将会错误。

在我所知道的至少一种架构上,所有可变参数条目都具有最大对齐,因为该函数不知道它正在获取什么。普通函数通过声明的类型对齐方式在堆栈上传递值。如果 printf 没有原型,C 语言将假定所有参数都是 int 并尝试以这种方式传递它们。同时 printf 函数本身将尝试将参数作为可变参数拉取,并且它很容易在这里或那里滑动几个字节。

© www.soinside.com 2019 - 2024. All rights reserved.