TL;DR:
- Compiler raises a warning. The behavior is undefined.
- But since the
undefined
behavior works in the company's favor, trying to find a solid reason for it to be corrected (changing 100s of lines of code, need to convince the manager)
sprintf warning
'0' flag used with ‘%s’ gnu_printf format
This behavior is undefined
according to this SO question/answer.
But in arm-gcc with the SW4STM32
tool chain (system workbench) the zeros are padded as needed.
MCVE
- For STM32
The below code is for an embedded system and for you to compile this you need the tool chain provided here. And for the remaining file please go 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){}
}
The above code will transmit data over UART which is then read using a PC-USB transceiver. The output for the above code is
#0000000001,0000000002,00000000000000000003,000000000000000000000000000000000000000000000000000000000004
As you can see even though a warning was raised the code performed/behaved as the programmer wanted it to.
This is a legacy code and this error has been written into many places. And so for me to fix it many lines must be fixed. But since the code performs as expected the manager doesn't want to change the code.
Question
- The code behaves as intended by the programmer, even though it is
undefined
. Will this undefined behavior change in the future breaking the code. - What argument can I make to make them fix this error?