A funny thing with sprintf

后端 未结 6 2002
伪装坚强ぢ
伪装坚强ぢ 2020-12-15 14:17

I\'m so confused with sprintf that a funny problem with different platfrom. Code :

int main () 
{
    char sql[1024];
    uint32_t app_id = 32;
    uint64_t          


        
相关标签:
6条回答
  • 2020-12-15 14:20

    Just adding to what others have said:

    Giving

    sprintf(sql, "%u, %u", app_id, task_id);
    

    instead of

    sprintf(sql, "%u, %u", task_id, app_id);
    

    gives an output 32, 64!!

    No need to worry! Here is why: task_id is pushed to stack (higher 4 bytes first and lower 4 bytes second) before pushing app_id (as arguments to sprintf). But when sprintf goes to take arguments, it pops 4 bytes + 4 bytes from stack, as two %u are specified in the format. So it takes the lower 4 bytes of task_id and prints it as unsigned int.

    The same happens when sprintf(sql, "%u, %u", task_id, app_id); is given.

    app_id is pushed first and task_id next. But when sprintf reads, it pops two 4 bytes, 64 (the lower 4 bytes of task_id) and 00 (higher 4 byte of task_id and prints 64, 00.

    0 讨论(0)
  • 2020-12-15 14:20

    As has been pointed out, the proper formatting specifier for uint64_t is PRIu64 (not lu, since there's no guarantee that uint64_t is long).

    So, you need to use that:

    #define __STDC_FORMAT_MACROS
    #include <inttypes.h>
    
    char sql[1024];
    uint32_t app_id = 32;
    uint64_t task_id = 64;
    sprintf(sql, "%u, %" PRIu64, app_id, task_id);
    printf ("%s\n", sql);
    
    0 讨论(0)
  • 2020-12-15 14:24

    Format string %lu won't work on 32-bit machines, where a 64-bit variable is long long.

    Use %llu for 64-bit instead:

    #include <stdio.h>
    #include <stdlib.h>
    #include <linux/types.h>
    #include <stdint.h>
    
    int main () 
    {
        char sql[1024];
        uint32_t app_id = 32;
        uint64_t task_id = 64;
        sprintf(sql, "%llu, %u", task_id, app_id);
        printf ("%s\n", sql);
        return 0;
    }
    
    0 讨论(0)
  • 2020-12-15 14:29

    Try:

    sprintf(sql, "%lu, %u", task_id, app_id);
    
    0 讨论(0)
  • 2020-12-15 14:38

    Use %llu format string for task_id in sprintf()as follows:

    sprintf(sql, "%llu, %u", task_id, app_id);
    //             ^
    //            for: long long unsigned int
    

    Edit: As @Simonc suggested its better to use: PRIu32 and PRIu64 macros defined in <inttypes.h> (as you have Linux tag) do like:

    sprintf(sql, "%"PRIu64", %"PRIu32"", task_id, app_id);
    //               ^           ^
    //       for:   uint64_t    uint32_t  
    
    0 讨论(0)
  • 2020-12-15 14:38

    The format specifier is wrong. The printf function doesn't know what kind of parameters are passed to it, it can only deduce this from the format specifiers. So when you pass a 64bit integer to it, and tell the function that you passed only a long (32bit) then it takes only half of the 64 bit value passed in. Depending on the architecture, the correct result might be printed or not. The reason is how the number is stored in memory and what the printf function sees when it reads the long value.

    If the long value happens to have the same number of bits or the value is stored in memory in such a way that the expected result happens to be in the right place, the correct value could be printed, but of course, the code would still be wrong, though it appears to work.

    0 讨论(0)
提交回复
热议问题