Define string array - c

I would like to define an array of string like that:
#define sup (const char**) ("string1", "string2")
but it fails when I try to print the first string:
printf("The string: %s\n",sup[0]);
how to do it in the proper way?

I would advice against doing this with macros altogether, but if you are really interested in what is going on with the code --more than in how this should actually be tackled, here is an explanation.
There is a simple issue in the code, and a more obscure one. The very simple is that to declare an array you don't use parenthesis but rather curly braces:
#define sup (const char**){"str1", "str2"} // still wrong!!
The less simple issue is that arrays are not pointers. The curly brace initializer can be used to initialize an array of two const char*, but that is not the same as a const char**. If you change the code to:
#define sup (const char*[2]){"str1", "str2" }
It should work.
What is going on under the hood with the previous version? Well, the compiler is seeing the declaration of a pointer (well, casting to a pointer) and the initializer. It is assuming that you want to initialize the pointer with the first element (incompatible pointer, but the cast is explicit... you must know what you want if you forced the cast), and then ignore the remainder. Basically the compiler translates your code to [*]:
#define sup (const char**)"str1"
And that will cause havoc at runtime. It is interesting to note that if you had used a proper variable and then initialized the pointer with it, it would have worked, because while arrays are not pointers (I insist, keep that in mind) arrays do decay into pointers:
const char* tmp[] = { "hi", "there" };
const char** sup = tmp; // fine, tmp decays into &tmp[0]
[*] There's a bit of handwaving there... the compiler translates the code, once inserted at the place of use of the macro by the preprocessor, but the translation is equivalent to what I wrote if you were to edit the macro manually.

I think that doing this kind of preprocessor tricks, especially with arrays, isn't such a good idea. You should instead have a real global string table, like this:
const char const * sup[]={"String 1", "String 2", "String 3"};
in one of the .c files, and put its extern declaration in a header to be included wherever such strings are needed:
extern const char const * sup[];
(the first const is to avoid modifications to each string literal - which is UB -, the second to avoid replacing the pointers stored in sup; if you want to allow this last action, remove the second const)
An alternative approach would be to define sup directly in the header as a static global variable (i.e. with internal linkage); I've seen this done before with integer constants to make sure they are immediately known to the compiler in every translation unit (so it can put them as immediate values in the generated assembly), but I don't think that with string pointers it can give any significant performance boost.

I have a header that is common to all my projects.
#define MAX_STUDENTS 3
char STUDENT[] = { "Manny", "Joe", "Jack" };
The code looks like:
for( int i=0; i<MAX_STUDENTS; i++ )
{ Do Something with STUDENT[i]; }
Claude

Related

C Aligning string literals for a specific use case

I'm trying to align string literals in a specific way, as how I'm using it in my code is fairly specific. I don't want to have to assign it to a variable, for instance many of my functions are using it as a direct argument. And I want it to work both in local scope or global scope.
Usage example:
char *str = ALIGNED_STRING("blah"); //what I want
foo(ALIGNED_STRING("blah")); //what I want
_Alignas(16) char str[] = "blah"; //not what I want (but would correctly align the string)
The ideal solution would be (_Alignas(16) char[]){ "blah" } or a worser case using the GCC/Clang compiler extensions for alignment (__attribute__((alignment(16))) char[]){ "blah" }, but neither works (they're ignored and the default alignment for the type is used).
So my next thought was to align it myself, and then my functions that use the string could then fix it up correctly. e.g. #define ALIGNED_STRING(str) (char*)(((uintptr_t)(char[]){ "xxxxxxxxxxxxxxx" str } + 16 - 1) & ~(16 - 1)) (where the string containing 'x' would represent data needed to understand where the real string can be found, that's easy but just for the example assume the 'x' is fine). Now that works fine in local scope, but fails in the global scope. Since the compiler complains about it not being a compile-time constant (error: initializer element is not a compile-time constant); I would've thought it would work but it seems only addition and subtraction are valid operations on the pointer at compile-time.
So I'm wondering if there's anyway to achieve what I want to do? At the moment I'm just using the latter example (padding and manually aligning) and avoiding to use it in the global scope (but I would really want to). And the best solution would avoid needing to make runtime adjustments (like using the alignment qualifier would), but that doesn't seem possible unless I apply it to a variable (but as mentioned that's not what I want to do).
Was able to get close to OP's need with a compound literal. (C99)
#include <stdio.h>
#include <stddef.h>
void bar(const char *s) {
printf("%p %s\n", (void*)s, s);
}
// v-- compound literal --------------------------v
#define ALIGNED_STRING(S) (struct { _Alignas(16) char s[sizeof S]; }){ S }.s
int main() {
char s[] = "12";
bar(s);
char t[] = "34";
bar(t);
bar(ALIGNED_STRING("asdfas"));
char *u = ALIGNED_STRING("agsdas");
bar(u);
}
Output
0x28cc2d 12
0x28cc2a 34
0x28cc30 asdfas // 16 Aligned
0x28cc20 agsdas // 16 Aligned

C string type definition

I was just trying to make a string like type when you could just write:
string s;
And I thought to do it like:
#define string char *
Then for example in main function I have to write only string s; and if I type different variable name then it doesn't work.
How can I improve the definition or maybe how can I use "typedef" for this job if it's not a bad practice to do it so. Or is there any better approach to make variables type of string?
I was searching but I think I couldn't find the answer.
You can't make variables of type string in C, because "string" is not a type.
A "string" is, by definition, "a contiguous sequence of characters terminated by and including the first null character". It's not a data type, it's a data format.
An array of char may contain a string. A char* may point to a string. Neither of them is a string.
If you like, you can define
typedef char *string; /* not recommended */
but that's misleading, since a variable of type char*, as I mentioned, isn't a string.
The best practice is simply to use char* directly. This makes it clear that your variable is a pointer. It's also consistent with the way the standard library is defined; for example, the strlen function is declared as:
size_t strlen(const char *s);
It's also consistent with the way most experienced C programmers write code that deals with strings.
Because of the way C treats arrays (more or less as second-class citizens), arrays, including arrays that contain strings, are usually manipulated via pointers to their elements. We can use pointer arithmetic to traverse an array. Pretending that the pointer is the array, or that it is a string, is tempting, and might seem to make the code more understandable, but in the long run it just causes confusion.
A macro approach like
#define string char*
is even worse than a typedef. Macros are expanded as sequences of tokens; the processor doesn't know about the syntax of C declarations. So given the above definition, this:
string x, y;
expands to
char* x, y;
which defines x as a char* and y as a char. If you need a name for a type, typedef is almost always better than #define.
You have to learn what the Preprocessor is. As for your problem, the right solution is
typedef char *string;
and if you want to use the preprocessor remove the semi colon and the s like this
#define string char *
In the second case the preprocessor will replace each occurence of string with char *, and hence if you declare
string x, y;
it will expand to
char *x, y;
where x if a pointer to char and y is simply a char, this is misleading and should be avoided.
One more thing, when working in C it is never a good Idea to hide the fact that some variable is a pointer, so things like
typedef SomeType *SomeTypeName;
where SomeType could be any type, are generally a bad idea, you can do something I've seen that clarifies this a little, you can append a P to SomeType, like this
typedef SomeType *SomeTypeP;
but I personally prefer the * to any of these typedefs
Don't. string is a C++ keyword. Not only it will cause problems if C++ becomes involved, but more importantly, it causes confusion and hides the fact that you are dealing with a pointer.
UPDATE: Right guys, it's not a keyword. But if like many people you put using namespace std; in your code, then string is a C++ class from the standard library.
What I wanted to say is that it is not a common practice to make an alias for char * and it might confuse other people looking at your code.

Why #defines instead of enums [duplicate]

Which one is better to use among the below statements in C?
static const int var = 5;
or
#define var 5
or
enum { var = 5 };
It depends on what you need the value for. You (and everyone else so far) omitted the third alternative:
static const int var = 5;
#define var 5
enum { var = 5 };
Ignoring issues about the choice of name, then:
If you need to pass a pointer around, you must use (1).
Since (2) is apparently an option, you don't need to pass pointers around.
Both (1) and (3) have a symbol in the debugger's symbol table - that makes debugging easier. It is more likely that (2) will not have a symbol, leaving you wondering what it is.
(1) cannot be used as a dimension for arrays at global scope; both (2) and (3) can.
(1) cannot be used as a dimension for static arrays at function scope; both (2) and (3) can.
Under C99, all of these can be used for local arrays. Technically, using (1) would imply the use of a VLA (variable-length array), though the dimension referenced by 'var' would of course be fixed at size 5.
(1) cannot be used in places like switch statements; both (2) and (3) can.
(1) cannot be used to initialize static variables; both (2) and (3) can.
(2) can change code that you didn't want changed because it is used by the preprocessor; both (1) and (3) will not have unexpected side-effects like that.
You can detect whether (2) has been set in the preprocessor; neither (1) nor (3) allows that.
So, in most contexts, prefer the 'enum' over the alternatives. Otherwise, the first and last bullet points are likely to be the controlling factors — and you have to think harder if you need to satisfy both at once.
If you were asking about C++, then you'd use option (1) — the static const — every time.
Generally speaking:
static const
Because it respects scope and is type-safe.
The only caveat I could see: if you want the variable to be possibly defined on the command line. There is still an alternative:
#ifdef VAR // Very bad name, not long enough, too general, etc..
static int const var = VAR;
#else
static int const var = 5; // default value
#endif
Whenever possible, instead of macros / ellipsis, use a type-safe alternative.
If you really NEED to go with a macro (for example, you want __FILE__ or __LINE__), then you'd better name your macro VERY carefully: in its naming convention Boost recommends all upper-case, beginning by the name of the project (here BOOST_), while perusing the library you will notice this is (generally) followed by the name of the particular area (library) then with a meaningful name.
It generally makes for lengthy names :)
In C, specifically? In C the correct answer is: use #define (or, if appropriate, enum)
While it is beneficial to have the scoping and typing properties of a const object, in reality const objects in C (as opposed to C++) are not true constants and therefore are usually useless in most practical cases.
So, in C the choice should be determined by how you plan to use your constant. For example, you can't use a const int object as a case label (while a macro will work). You can't use a const int object as a bit-field width (while a macro will work). In C89/90 you can't use a const object to specify an array size (while a macro will work). Even in C99 you can't use a const object to specify an array size when you need a non-VLA array.
If this is important for you then it will determine your choice. Most of the time, you'll have no choice but to use #define in C. And don't forget another alternative, that produces true constants in C - enum.
In C++ const objects are true constants, so in C++ it is almost always better to prefer the const variant (no need for explicit static in C++ though).
The difference between static const and #define is that the former uses the memory and the later does not use the memory for storage. Secondly, you cannot pass the address of an #define whereas you can pass the address of a static const. Actually it is depending on what circumstance we are under, we need to select one among these two. Both are at their best under different circumstances. Please don't assume that one is better than the other... :-)
If that would have been the case, Dennis Ritchie would have kept the best one alone... hahaha... :-)
In C #define is much more popular. You can use those values for declaring array sizes for example:
#define MAXLEN 5
void foo(void) {
int bar[MAXLEN];
}
ANSI C doesn't allow you to use static consts in this context as far as I know. In C++ you should avoid macros in these cases. You can write
const int maxlen = 5;
void foo() {
int bar[maxlen];
}
and even leave out static because internal linkage is implied by const already [in C++ only].
Another drawback of const in C is that you can't use the value in initializing another const.
static int const NUMBER_OF_FINGERS_PER_HAND = 5;
static int const NUMBER_OF_HANDS = 2;
// initializer element is not constant, this does not work.
static int const NUMBER_OF_FINGERS = NUMBER_OF_FINGERS_PER_HAND
* NUMBER_OF_HANDS;
Even this does not work with a const since the compiler does not see it as a constant:
static uint8_t const ARRAY_SIZE = 16;
static int8_t const lookup_table[ARRAY_SIZE] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; // ARRAY_SIZE not a constant!
I'd be happy to use typed const in these cases, otherwise...
If you can get away with it, static const has a lot of advantages. It obeys the normal scope principles, is visible in a debugger, and generally obeys the rules that variables obey.
However, at least in the original C standard, it isn't actually a constant. If you use #define var 5, you can write int foo[var]; as a declaration, but you can't do that (except as a compiler extension" with static const int var = 5;. This is not the case in C++, where the static const version can be used anywhere the #define version can, and I believe this is also the case with C99.
However, never name a #define constant with a lowercase name. It will override any possible use of that name until the end of the translation unit. Macro constants should be in what is effectively their own namespace, which is traditionally all capital letters, perhaps with a prefix.
#define var 5 will cause you trouble if you have things like mystruct.var.
For example,
struct mystruct {
int var;
};
#define var 5
int main() {
struct mystruct foo;
foo.var = 1;
return 0;
}
The preprocessor will replace it and the code won't compile. For this reason, traditional coding style suggest all constant #defines uses capital letters to avoid conflict.
It is ALWAYS preferable to use const, instead of #define. That's because const is treated by the compiler and #define by the preprocessor. It is like #define itself is not part of the code (roughly speaking).
Example:
#define PI 3.1416
The symbolic name PI may never be seen by compilers; it may be removed by the preprocessor before the source code even gets to a compiler. As a result, the name PI may not get entered into the symbol table. This can be confusing if you get an error during compilation involving the use of the constant, because the error message may refer to 3.1416, not PI. If PI were defined in a header file you didn’t write, you’d have no idea where that 3.1416 came from.
This problem can also crop up in a symbolic debugger, because, again, the name you’re programming with may not be in the symbol table.
Solution:
const double PI = 3.1416; //or static const...
I wrote quick test program to demonstrate one difference:
#include <stdio.h>
enum {ENUM_DEFINED=16};
enum {ENUM_DEFINED=32};
#define DEFINED_DEFINED 16
#define DEFINED_DEFINED 32
int main(int argc, char *argv[]) {
printf("%d, %d\n", DEFINED_DEFINED, ENUM_DEFINED);
return(0);
}
This compiles with these errors and warnings:
main.c:6:7: error: redefinition of enumerator 'ENUM_DEFINED'
enum {ENUM_DEFINED=32};
^
main.c:5:7: note: previous definition is here
enum {ENUM_DEFINED=16};
^
main.c:9:9: warning: 'DEFINED_DEFINED' macro redefined [-Wmacro-redefined]
#define DEFINED_DEFINED 32
^
main.c:8:9: note: previous definition is here
#define DEFINED_DEFINED 16
^
Note that enum gives an error when define gives a warning.
The definition
const int const_value = 5;
does not always define a constant value. Some compilers (for example tcc 0.9.26) just allocate memory identified with the name "const_value". Using the identifier "const_value" you can not modify this memory. But you still could modify the memory using another identifier:
const int const_value = 5;
int *mutable_value = (int*) &const_value;
*mutable_value = 3;
printf("%i", const_value); // The output may be 5 or 3, depending on the compiler.
This means the definition
#define CONST_VALUE 5
is the only way to define a constant value which can not be modified by any means.
Although the question was about integers, it's worth noting that #define and enums are useless if you need a constant structure or string. These are both usually passed to functions as pointers. (With strings it's required; with structures it's much more efficient.)
As for integers, if you're in an embedded environment with very limited memory, you might need to worry about where the constant is stored and how accesses to it are compiled. The compiler might add two consts at run time, but add two #defines at compile time. A #define constant may be converted into one or more MOV [immediate] instructions, which means the constant is effectively stored in program memory. A const constant will be stored in the .const section in data memory. In systems with a Harvard architecture, there could be differences in performance and memory usage, although they'd likely be small. They might matter for hard-core optimization of inner loops.
Don't think there's an answer for "which is always best" but, as Matthieu said
static const
is type safe. My biggest pet peeve with #define, though, is when debugging in Visual Studio you cannot watch the variable. It gives an error that the symbol cannot be found.
Incidentally, an alternative to #define, which provides proper scoping but behaves like a "real" constant, is "enum". For example:
enum {number_ten = 10;}
In many cases, it's useful to define enumerated types and create variables of those types; if that is done, debuggers may be able to display variables according to their enumeration name.
One important caveat with doing that, however: in C++, enumerated types have limited compatibility with integers. For example, by default, one cannot perform arithmetic upon them. I find that to be a curious default behavior for enums; while it would have been nice to have a "strict enum" type, given the desire to have C++ generally compatible with C, I would think the default behavior of an "enum" type should be interchangeable with integers.
A simple difference:
At pre-processing time, the constant is replaced with its value.
So you could not apply the dereference operator to a define, but you can apply the dereference operator to a variable.
As you would suppose, define is faster that static const.
For example, having:
#define mymax 100
you can not do printf("address of constant is %p",&mymax);.
But having
const int mymax_var=100
you can do printf("address of constant is %p",&mymax_var);.
To be more clear, the define is replaced by its value at the pre-processing stage, so we do not have any variable stored in the program. We have just the code from the text segment of the program where the define was used.
However, for static const we have a variable that is allocated somewhere. For gcc, static const are allocated in the text segment of the program.
Above, I wanted to tell about the reference operator so replace dereference with reference.
We looked at the produced assembler code on the MBF16X... Both variants result in the same code for arithmetic operations (ADD Immediate, for example).
So const int is preferred for the type check while #define is old style. Maybe it is compiler-specific. So check your produced assembler code.
I am not sure if I am right but in my opinion calling #defined value is much faster than calling any other normally declared variable (or const value).
It's because when program is running and it needs to use some normally declared variable it needs to jump to exact place in memory to get that variable.
In opposite when it use #defined value, the program don't need to jump to any allocated memory, it just takes the value. If #define myValue 7 and the program calling myValue, it behaves exactly the same as when it just calls 7.

How to initialize a dynamic array of pointers to NULL in C?

I am fairly new to C and I don't understand why the following two statements do not create the same result:
char *fields[14] = {NULL};
const int num_fields = 14;
char *fields[num_fields] = {NULL};
Option 1 works, but option 2 does not. It says "variable-sized object may not be initialized" and it gives a warning "warning: excess elements in array initializer". I use gcc 4.2.1 on OSX.
Thanks for sharing your thoughts!
The second object is called a VLA (Variable Length Array), well defined by C99. To achieve what you want you can use this:
for (i = 0; i < num_fields; i++)
fields[i] = NULL;
The gist of the issue is that const int num_fields is very different from 14, it's not a constant, it's read-only.
Even if you define num_fields with const keyword, compiler interprets it as variable only. you can have alternative for this by defining following macro:
#define num_fields 14
char *fields[num_fields] = {NULL};
Although num_fields has a const qualifier, it is still considered a variable by the compiler.
Therefore, you are attempting to declare a variable-sized array, and initialisers (the {NULL} part) cannot be used in conjunction with them.
Your construction works in C++, where a const int will be treated as a compile-time constant ("constant expression"), and hence available for use as a compile-time array size.
(This aspect was one of B. Stroustrup's design goals for C++, to eliminate the need for compile-time macros if possible)
However in C, your definition of "num_fields" effectively declares a read-only memory location with your preset value, and hence is not under C rules a "constant expression" valid at compile time, and hence may not be used as an array size at the outermost 'program' scope.

How do you declare string constants in C?

I know it's quite idiomatic, or good style at least, in C to declare numeric constants as enums instead of #defineing them.
/* bad style */
#define MAXLINE 1024
/* good/better style */
enum {
MAX_LINE = 1024
};
Is there an equivalent rule for the definition of string constants?
/* is this good style? */
#define HELLO "Hello World"
/* or is this better? */
const char *HELLO2 = "Howdy";
What do you prefer? If possible show some drawbacks of either method.
There's one more (at least) road to Rome:
static const char HELLO3[] = "Howdy";
(static — optional — is to prevent it from conflicting with other files). I'd prefer this one over const char*, because then you'll be able to use sizeof(HELLO3) and therefore you don't have to postpone till runtime what you can do at compile time.
The define has an advantage of compile-time concatenation, though (think HELLO ", World!") and you can sizeof(HELLO) as well.
But then you can also prefer const char* and use it across multiple files, which would save you a morsel of memory.
In short — it depends.
One advantage (albeit very slight) of defining string constants is that you can concatenate them at compile time:
#define HELLO "hello"
#define WORLD "world"
puts( HELLO WORLD );
Not sure that's really an advantage, but it is a technique that cannot be used with const char *'s.
If you want a "const string" like your question says, I would really go for the version you stated in your question:
/* first version */
const char *HELLO2 = "Howdy";
Particularly, I would avoid:
/* second version */
const char HELLO2[] = "Howdy";
Reason: The problem with second version is that compiler will make a copy of the entire string "Howdy", PLUS that string is modifiable (so not really const).
On the other hand, first version is a const string accessible by pointer HELLO2, and it can not be modified.
The main disadvantage of the #define method is that the string is duplicated each time it is used, so you can end up with lots of copies of it in the executable, making it bigger.
Their are a few differences.
#define HELLO "Hello World"
The statement above can be used with preprocessor and can only be change in the preprocessor.
const char *HELLO2 = "Howdy";
The statement above can be changed with c code. Now you can't change the each individual character around like the statement below because its constant.
HELLO2[0] = 'a'
But you what you can do is have it point to a different string like the statement
below
HELLO2 = "HELLO WOLRD"
It really depends on how you want to be able to change the variable around.
With the preprocessor or c code.

Resources