[英]Dynamic type casting in C
我正在嘗試編寫一個以緩沖區(void *),類型大小,類型名稱和元素數量為參數的函數。 緩沖區可能包含有限數量的基本類型(int,float,double,...)的值。 在這個函數中,我希望能夠增加每個值。 看起來像這樣:
void increment (void *buffer, int type_size, char *type_name, int n_elements)
{
for (int i=0; i<n_elements; i++)
((MACRO(type_name))(buffer))[i]++; // ???
return;
}
我的問題很簡單:如何動態地釋放緩沖區? 如果需要,我可以添加更多的功能參數。 也許可以使用宏來完成某些工作,但我無法弄清楚。
請改用宏:
INCREMENT (buffer, n_elements) \
{\
for (typeof(n_elements) i=0; i < n_elements; i++)\
(buffer)[i]++;\
}
或更好(也適用於浮點類型):
INCREMENT (buffer, n_elements) \
{\
for (typeof(n_elements) i=0; i < n_elements; i++)\
(buffer)[i] += 1;\
}
typeof(n_elements)
(*)是為了避免有符號/無符號比較問題。 如果使用例如INCREMENT (buffer + 4, 12)
調用宏,則在buffer
周圍加括號可以防止出現問題。
在調用方,它看起來像這樣:
double buffer[100];
//[...] Initialize here your buffer
INCREMENT (buffer, 100); //Semicolon is optional, but I prefer having it
要么
#define BUFFER_SIZE 200
unsigned int* p = malloc(sizeof(*p) * BUFFER_SIZE);
//[...] Initialize here your buffer
INCREMENT (p, BUFFER_SIZE); //Semicolon is optional, but I prefer having it
typeof
實際上不是標准的,C11中的_Generic
給出了一種解決方法,有關詳細信息,請參見此處 。
如果要處理的特定類型數量有限,則可以為每種類型編寫一個單獨的函數。 如果您不想為每種類型選擇正確的功能,則可以使用C11的_Generic
根據類型進行選擇。 作為一個基本示例:
#include <stdio.h>
#include <stdlib.h>
void increment_int(int *, int);
void increment_long_long_int(long long int *, int);
#define increment(buffer, n_elements) _Generic((buffer), \
int *: increment_int, \
long long int *: increment_long_long_int \
)(buffer, n_elements)
void increment_long_long_int (long long int *buffer, int n_elements)
{
for (int i=0; i<n_elements; i++)
{
buffer[i]++;
}
return;
}
void increment_int (int *buffer, int n_elements)
{
for (int i=0; i<n_elements; i++)
{
buffer[i]++;
}
return;
}
int main(void) {
int buff[20] = {0};
long long int buff2[20] = {0};
increment(buff, 20);
increment(buff2, 20);
printf("%d\n", buff[5]);
printf("%lld\n", buff2[8]);
return EXIT_SUCCESS;
}
您只能擁有像這樣的愚蠢的東西(gcc版本):
#include <stdint.h>
void incrementAlmostAnySize(void *ptr, size_t size, size_t element, int sign)
{
union
{
uint8_t u8;
uint16_t u16;
uint32_t u32;
uint64_t u64;
int8_t i8;
int16_t i16;
int32_t i32;
int64_t i64;
}*uptr = ptr + size * element; //non gcc : (void *)((uint8_t *)ptr + size * element);
if(sign)
{
switch(size)
{
case 1:
uptr -> i8++;
break;
case 2:
uptr -> i16++;
break;
case 4:
uptr -> i32++;
break;
case 8:
uptr -> i64++;
break;
default:
break;
}
}
else
{
switch(size)
{
case 1:
uptr -> u8++;
break;
case 2:
uptr -> u16++;
break;
case 4:
uptr -> u32++;
break;
case 8:
uptr -> u64++;
break;
default:
break;
}
}
}
用法:
char x[1000];
void foo()
{
incrementAlmostAnySize(x, sizeof(long long), 10, 1);
incrementAlmostAnySize(x, sizeof(uint32_t), 2, 0);
for(size_t i = 0; i < sizeof(x) / sizeof(uint64_t); i ++)
incrementAlmostAnySize(x, sizeof(uint64_t), i, 0);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.