Как уже отмечалось, прямая проблема заключается в том, что вы пытаетесь вызвать sprintf
из вне функции.
Вы упомянули, что вы устанавливаете строки таким образом, потому что вы сами используете SITE_NAME
в дополнение к конкатенации с помощью пути, и вы хотите изменить его только в одном месте. Это хорошая цель, известная в некоторых кругах как "don't repeat yourself" (often abbreviated DRY). Однако, даже если код работал (например, потому что вы переместили sprintf
вызов в основной), вы на самом деле не достигли своей цели из-за следующей строкой:
char SITE_ROOT[19];
Вы объявляете массив фиксированной длины точно большой достаточно, чтобы провести "/var/www/html/test"
, который просто просит переполнение буфера. Когда вы меняете SITE_NAME
от "test"
до, например, "someRealSiteName"
, вы, скорее всего, перепишете что-нибудь еще, когда вы соединитесь, вызывая непредсказуемые результаты. Поэтому вам нужно вручную пересчитать длину финальной строки и обновить размер массива (что было бы легко ошибиться, скажем, забыв добавить 1 для нулевого терминатора) каждый раз, когда вы меняете SITE_NAME
.
Вы можете, конечно, ограничить длину SITE_NAME
и размер SITE_ROOT
, чтобы провести максимально возможный путь, но это был бы искусственный лимит, и вы могли бы в конечном итоге тратить пространство. Кроме того, вам все равно придется проверять, не превышена ли длина во время выполнения (или использовать функцию, которая будет игнорировать дополнительные символы).
Вместо этого, вы можете динамически изменять размер SITE_ROOT
так:
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
const char SITE_PATH[] = "/var/www/html/";
const char SITE_NAME[] = "someRealSiteName";
char *SITE_ROOT = NULL; // just making this explicit, would be set to 0 anyway
int main(void)
{
size_t siteRootLength = strlen(SITE_PATH) + strlen(SITE_NAME);
SITE_ROOT = malloc(siteRootLength + 1); //don't forget to account for the terminating '\0'
strcpy(SITE_ROOT, SITE_PATH);
strcat(SITE_ROOT, SITE_NAME);
printf("%s\n", SITE_NAME):
printf("%s\n", SITE_PATH):
printf("%s\n", SITE_ROOT):
return 0;
}
Это решение хорошо, но имеет некоторые недостатки:
SITE_ROOT
не может быть const
указатель, так как строка, так и сам указатель могут быть случайно изменены
- Путь и имя сайта будут храниться в памяти дважды (хотя похоже, что с этим все в порядке)
- конкатенации делается во время выполнения, когда это может быть сделано во время компиляции
- код более и более сложными, чем это необходимо для такой простой задачи
- Риск того, что
SITE_ROOT
используется, прежде чем он имеет правильное значение (или даже действительный указатель/строка!) в другом коде инициализации или другом потоке.
Я чувствую что-то вроде следующего лучше:
#include <stdio.h>
#define SITE_PATH_MACRO "/var/www/html/"
#define SITE_NAME_MACRO "someRealSiteName"
// the preprocessor will merge the two string literals into one
#define SITE_ROOT_MACRO SITE_PATH_MACRO SITE_NAME_MACRO
// you could do without some or all of these if you don't need them
// (or are willing to use the macros directly)
const char SITE_PATH[] = SITE_PATH_MACRO;
const char SITE_NAME[] = SITE_NAME_MACRO;
const char SITE_ROOT[] = SITE_ROOT_MACRO;
int main(void)
{
printf("%s\n", SITE_NAME);
printf("%s\n", SITE_PATH);
printf("%s\n", SITE_ROOT);
return 0;
}
Какая линия дает вам ошибку? –
@JackManey - Я обновил свой пост ... ошибка находится на линии sprintf. – user983223
Неожиданный макрос может быть запутанным. Проверьте выход препроцессора. ('cc -E file.c' для unix-подобных компиляторов, расскажите, какой компилятор вы используете, если вам нужна дополнительная помощь) –