Избегайте «предупреждение: приведение к указателю из целого числа разного размера [-Wint-to-pointer-cast]» в макросе _generi c - PullRequest
1 голос
/ 12 марта 2020

Следующий код работает как задумано,


#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>

#define GEN__INTEGER_ 0 
#define GEN__STRING_ 1 
#define GEN__U8_ARRAY_ 2
#define GEN__U16_ARRAY_ 3
#define GEN__U32_ARRAY_ 4

#define INTEGER_EQUAL(observed,expected)        (observed == expected)
#define STRING_EQUAL(observed,expected)         (strcmp((char *)observed, (char *)expected) == 0)
#define U8_ARRAY_EQUAL(observed,expected)       (memcmp((uint8_t *)observed, (uint8_t *)expected, sizeof(expected)/sizeof(uint8_t)) == 0)
#define U16_ARRAY_EQUAL(observed,expected)      (memcmp((uint16_t *)observed, (uint16_t *)expected, sizeof(expected)/sizeof(uint16_t)) == 0)
#define U32_ARRAY_EQUAL(observed,expected)      (memcmp((uint32_t *)observed, (uint32_t *)expected, sizeof(expected)/sizeof(uint32_t)) == 0)
#define GENERIC_EQUAL(observed,expected)        do{ \
                                                   printf("Is "#observed" equal to "#expected" ? "); \
                                                   if( _Generic( \
                                                   (observed)+0, \
                                                   default:   INTEGER_EQUAL(observed,expected), \
                                                   char *:    STRING_EQUAL(observed,expected), \
                                                   uint8_t *: U8_ARRAY_EQUAL(observed,expected), \
                                                   uint16_t *: U16_ARRAY_EQUAL(observed,expected), \
                                                   uint32_t *: U32_ARRAY_EQUAL(observed,expected) \
                                                   )) {printf("[OK]\n");} else {printf("[FAILS]\n");}\
                                                }while(0)

#define INTEGER_PRINT(data)     printf("integer : %d\n",data)
#define STRING_PRINT(data)      printf("string : %s\n",data);
#define U8_ARRAY_PRINT(data)    do{ \
                                    uint8_t gen_buf_[sizeof(data)]; \
                                    memcpy(gen_buf_,(uint8_t*)data,sizeof(data)); \
                                    printf("arr_u8 : "); \
                                    for(uint8_t _igen_ = 0; _igen_<sizeof(data)/sizeof(uint8_t);_igen_++) \
                                    {  \
                                       printf("%d,",gen_buf_[_igen_]); \
                                    } \
                                    printf("\n"); \
                                }while(0)

#define GENERIC_PRINT(data)     do{\
                                    switch(_Generic( \
                                            (data)+0, \
                                            default:   GEN__INTEGER_, \
                                            char *:    GEN__STRING_, \
                                            uint8_t *: GEN__U8_ARRAY_, \
                                            uint16_t *: GEN__U16_ARRAY_, \
                                            uint32_t *: GEN__U32_ARRAY_ \
                                          )){  \
                                        case GEN__STRING_: STRING_PRINT(data); break;\
                                        case GEN__U8_ARRAY_: U8_ARRAY_PRINT(data); break;\
                                        case GEN__U16_ARRAY_: U8_ARRAY_PRINT(data); break; \
                                        case GEN__U32_ARRAY_: U8_ARRAY_PRINT(data); break; \
                                        default: INTEGER_PRINT(data); break; \
                                    } \
                                } while(0)

int main()
{
    uint8_t integ1 = 0;
    uint8_t integ2 = 1;
    GENERIC_EQUAL(integ1,integ2);
    GENERIC_PRINT(integ1);

    char string1[]="abc";
    char string2[]="abc";
    GENERIC_EQUAL(string1,string2);
    GENERIC_PRINT(string1);

    uint8_t array0[]={1,2};
    uint8_t array1[]={1,2};
    uint8_t array2[]={1,3};
    uint8_t array3[]={1,2,3,4};
    GENERIC_EQUAL(array1,array0);
    GENERIC_EQUAL(array1,array2);
    GENERIC_EQUAL(array1,array3);
    GENERIC_PRINT(array1);
    GENERIC_PRINT(array2);
    GENERIC_PRINT(array3);

    return 0;
}

, но выдает следующие предупреждения:

main.c:16:78: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]                                   
main.c:25:63: note: in expansion of macro ‘U8_ARRAY_EQUAL’                                                                      
main.c:69:5: note: in expansion of macro ‘GENERIC_EQUAL’                                                                        
main.c:17:57: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]                                   
[...]
main.c:81:5: note: in expansion of macro ‘GENERIC_PRINT’                                                                        
main.c:35:53: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]                
[...]                                                                                                     
main.c:31:40: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘uint8_t * {aka unsigned char *}’ [  
-Wformat=]                                                                                                                      
main.c:70:50: note: in expansion of macro ‘INTEGER_PRINT’                                                                       
main.c:97:5: note: in expansion of macro ‘GENERIC_PRINT’                                                  

Есть ли способ избежать первых предупреждений [-Wint-to-pointer -cast]?

Я не могу звонить без каста ...

1 Ответ

1 голос
/ 12 марта 2020

Итак, проблема здесь в том, как вы используете указатели в каждом макросе.

Например, макрос U8_ARRAY_EQUAL(integ1, integ2) расширяется до:

(memcmp((uint8_t *)integ1, (uint8_t *)integ2, sizeof(integ2)/sizeof(uint8_t)) == 0)

Что означает, что вы применяете значение Integ1 и Integ2 для указателей, а не их адресов памяти.

Исправление для этого будет определять макросы как:

#define U8_ARRAY_EQUAL(observed,expected) (memcmp((uint8_t *)&observed, (uint8_t *)&expected, sizeof(expected)/sizeof(uint8_t)) == 0)

Обратите внимание на &? Таким образом, вы на самом деле говорите memcmp сравнивать область памяти, которая содержит integ1 и integ2, вместо того, чтобы приводить их значения и пытаться использовать их в качестве адресов памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...