2012-06-06 4 views
1

У меня есть несколько ярлыков для объектов камеры, и я пытаюсь сэкономить память (очень скупое окружение памяти). Вот моя текущая версия, с использованием статического константного массива и макрос:Макро для замены многих строковых констант

В заголовке:

#define NUM_CAMERAS   6   
static const char* CAM_LABELS[NUM_CAMERAS] = { "Camera1", 
               "Camera2", 
               "Camera3", 
               "752x480_cam", 
               "std_cam", 
               "wide_cam" }; 
#define CAM_LABEL(id)   id<=NUM_CAMERAS?CAM_LABELS[id-1]:"cam id error" 

Использование в программе:

int cam = 3;  
pritnf("Configuring camera id [%d], label: [%s]\n",cam, CAM_LABEL(cam)); 

Вышеуказанные работы, но я хотел используйте макросы для замены статического массива const, поэтому мне бы хотелось, чтобы что-то в заголовке было больше похоже:

#define NUM_CAMERAS  6 
#define CAM_LABEL1  "Camera1" 
#define CAM_LABEL2  "Camera2" 
#define CAM_LABEL3  "Camera3" 
#define CAM_LABEL4  "752x480_cam" 
#define CAM_LABEL5  "std_cam" 
#define CAM_LABEL6  "wide_cam" 
#define CAM_LABEL(id)  /* myster code */ 

Есть ли способ передать целочисленное значение как «id» выше, а затем воссоздать известное значение CAM_LABEL ##? Я попробовал несколько комбинаций макроса ## gluing, но он помещал бы в «cam» или любое другое имя переменной в макрос, вместо этого значения переменных. Я, наверное, пропустил что-то очень очевидное.

Заранее спасибо.

+1

Значение 'cam' доступно только во время выполнения, расширение макроса до компиляции, поэтому он не может работать таким образом. –

+0

Я знал, что есть очевидная причина. Большое спасибо за разъяснение. – user1440556

ответ

4

Не уверен, что, если я понял вашу проблему, но это отлично работает для меня:

#include <stdio.h> 

#define CAM_LABEL1  "Camera1" 
#define CAM_LABEL2  "Camera2" 
#define CAM_LABEL3  "Camera3" 
#define CAM_LABEL4  "752x480_cam" 
#define CAM_LABEL5  "std_cam" 
#define CAM_LABEL6  "wide_cam" 

#define CAM(n) CAM_LABEL##n 

int main(int argc, const char *argv[]) 
{ 
    printf("CAM: [%s], [%s]\n",CAM(2),CAM(3)); 
} 

Однако, я не думаю, что это будет эффективным для экономии памяти (который, кажется, главная забота). Вы рассчитываете на то, что компилятор сжимает постоянные строки, которые идентичны, так что каждый экземпляр «Camera1» заменяется одним и тем же указателем (и сама строка сохраняется только один раз). Это не гарантируется; in:

printf("%s, %s\n","Camera1","Camera1"); 

Это законно для компилятора, чтобы создать ДВА ШПИРАТОВ.

Я хотел бы предложить вам создать одну строку и смещение вектора:

const char *cam_labels="Camera1\0Camera2\0Camera3"; 
const char *cam_labels_offset = "\x00\x08\x10"; 

#define CAM(x) (cam_labels+cam_labels_offset[x]) 
int main(int argc, const char *argv[]) 
{ 
    printf("CAM: [%s], [%s]\n",CAM(0),CAM(2)); 
} 

Вы должны добавить некоторый контроль, чтобы избежать неприятных вещей, чтобы произойти (но с учетом риска двойной оценки), и если общая длина строк больше 255, вам нужно будет представить смещения с двумя байтами.

Вы также должны написать небольшую подпрограмму, чтобы получить смещения, считая их вручную, было бы слишком подвержено ошибкам.

Пусть p - размер (char *) в вашей системе, n число меток и s сумма длины строк (включая окончание \ 0).

Ваш первый подход (тот, который содержит массив указателей на строки), потребует сохранения n * p + s байтов, ваш второй подход (с макросами) действительно зависит от компилятора, тот, который я предлагаю, будет нуждаться в 2p + з + п.

Смежные вопросы