TL; DR :
undefined
行为对公司有利,因此设法找到纠正该问题的坚实理由(更改几百行代码,需要说服经理)sprintf警告
'0'标志与'%s'gnu_printf格式一起使用
根据this这样的问题/答案,这种行为是undefined
。
但是在具有SW4STM32
工具链(system workbench)的arm-gcc中,需要根据需要填充零。
MCVE
以下代码适用于嵌入式系统,要编译此代码,您需要使用here提供的工具链。对于其余文件,请转到here。
#include "stm32f4xx_hal.h"
#include "stm32f4_discovery.h"
/* Private define ------------------------------------------------------------*/
#define TXBUFFERSIZE 100
/* Definition for USARTx clock resources */
#define USARTx USART2
#define USARTx_CLK_ENABLE() __USART2_CLK_ENABLE();
#define USARTx_RX_GPIO_CLK_ENABLE() __GPIOA_CLK_ENABLE()
#define USARTx_TX_GPIO_CLK_ENABLE() __GPIOA_CLK_ENABLE()
#define USARTx_FORCE_RESET() __USART2_FORCE_RESET()
#define USARTx_RELEASE_RESET() __USART2_RELEASE_RESET()
/* Definition for USARTx Pins */
#define USARTx_TX_PIN GPIO_PIN_2
#define USARTx_TX_GPIO_PORT GPIOA
#define USARTx_TX_AF GPIO_AF7_USART2
#define USARTx_RX_PIN GPIO_PIN_3
#define USARTx_RX_GPIO_PORT GPIOA
#define USARTx_RX_AF GPIO_AF7_USART2
/* Private variables ---------------------------------------------------------*/
/* UART handler declaration */
UART_HandleTypeDef UartHandle;
/* Private function prototypes -----------------------------------------------*/
static void SystemClock_Config(void);
static void Error_Handler(void)
static void UART_Init(void);
/* Private functions ---------------------------------------------------------*/
int main(void)
{
HAL_Init();
/* Configure the system clock to 168 Mhz */
SystemClock_Config();
UART_Init();
char pkt_buff[TXBUFFERSIZE+2];
memset(pkt_buff, 0, sizeof(pkt_buff));
sprintf(pkt_buff, "#%010s,%010s,%020s,%060s\r", "1", "2", "3", "4");
if(HAL_UART_Transmit(&UartHandle, (uint8_t*)pkt_buff, TXBUFFERSIZE, 5000)!= HAL_OK)
{
Error_Handler();
}
while(1) {
}
}
static void UART_Init(void)
{
/*##-1- Configure the UART peripheral ######################################*/
/* Put the USART peripheral in the Asynchronous mode (UART Mode) */
/* UART1 configured as follow:
- Word Length = 8 Bits
- Stop Bit = One Stop bit
- Parity = None
- BaudRate = 9600 baud
- Hardware flow control disabled (RTS and CTS signals) */
UartHandle.Instance = USARTx;
UartHandle.Init.BaudRate = 9600;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits = UART_STOPBITS_1;
UartHandle.Init.Parity = UART_PARITY_NONE;
UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
UartHandle.Init.Mode = UART_MODE_TX_RX;
if(HAL_UART_Init(&UartHandle) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief System Clock Configuration
* The system Clock is configured as follow :
* System Clock source = PLL (HSE)
* SYSCLK(Hz) = 168000000
* HCLK(Hz) = 168000000
* AHB Prescaler = 1
* APB1 Prescaler = 4
* APB2 Prescaler = 2
* HSE Frequency(Hz) = 8000000
* PLL_M = 8
* PLL_N = 336
* PLL_P = 2
* PLL_Q = 7
* VDD(V) = 3.3
* Main regulator output voltage = Scale1 mode
* Flash Latency(WS) = 5
* @param None
* @retval None
*/
static void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
/* Enable Power Control clock */
__PWR_CLK_ENABLE();
/* The voltage scaling allows optimizing the power consumption when the device is
clocked below the maximum system frequency, to update the voltage scaling value
regarding system frequency refer to product datasheet. */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/* Enable HSE Oscillator and activate PLL with HSE as source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
}
static void Error_Handler(void)
{
while(1){}
}
以上代码将通过UART传输数据,然后使用PC-USB收发器读取数据。上面代码的输出是
#0000000001,0000000002,00000000000000000003,000000000000000000000000000000000000000000000000000000000004
您可以看到,即使发出警告,也可以按照程序员的意愿执行/执行代码。
这是旧版代码,并且此错误已被写入许多地方。因此,要我修复此问题,必须修复许多行。但是由于代码按预期执行,经理不希望更改代码。
问题
undefined
,代码也可以按照程序员的预期运行。这种未定义的行为将来会改变代码吗?答案 0 :(得分:2)
未定义的行为就是未定义的行为。 应用程序实际上可以在UB之后执行任何操作。它可能正在从RAM的某个位置读取一个值,并使用该值确定是否对填充进行零填充,或者可以正确对字符串进行零填充但决定完全破坏所有字符串。您的堆栈框架。或在不相关的代码区域中默默地将减法更改为加法。
未定义的行为是未定义的。任何事情都会发生。
有人指出,“ ”但是,由于未定义的行为对公司有利,所以……” 对于给定的一组起始条件。对于当时存在的代码库。只要您在任何地方进行单个更改,所有投注都将关闭。
话虽如此,最有可能的情况是编译器选择了定义行为,而该行为恰好是您所期望的行为。在这种情况下,杰布的答案可能对您有用。但是就我个人而言,无论副作用如何无害,我都永远不会依赖未定义的行为。答案 1 :(得分:1)
我不会更改代码,因为当前的工具链会产生所需的行为(不要更改正在运行的系统)。
但是您可以在当前版本的工具链中添加一个锁。
像
#if !defined(__ARMCC_VERSION) || (__ARMCC_VERSION != 4711)
#error DON'T CHANGE THE TOOLCHAIN, check if 'sprintf("%010s", "1" )' still works!
#endif
为确保您的工具链不会出现不确定的行为,应查看sprintf.c / vsprintf.c源代码。