Readed bog of Ulrich Drepper and come across 2 entries that looks like conficting.
In the first one (string in global space) Ulrich states that the string should be defines as:
const char _pcre_ucp_names[] = "blabla";
while already in second one (string in function) he argues it should be declared as:
static const char _pcre_ucp_names[] = "blabla";
Can you explain what is the better name to declate a string?
UDP:
First of all I removed C++ tag - this question is valid for C as well for C++. So I don't think answers which explain what static means in class/function/file scope is relevant.
Read the articles before answering. The articles deal about memory usage - where the actual data is stored (in .rodata or in .data section), do the string should be relocated (if we're talking about unix/linux shared objects), is it possible to change the string or not.
UDP2
In first one it's said that for global variable following form:
(1) const char *a = "...";
is less good than
(2) const char a[] = "..."
Why? I always thought that (1) is better, since (2) actually replicate the string we assign it, while (1) only points to string we assign.
It depends—if you need the string to be visible to other source files in a project, you can't declare it static. If you only need to access it from the file where it's defined, then you probably want to use static.
The blog post you mention was talking about something different, though:
#include <stdio.h>
#include <string.h>
int main(void)
{
const char s[] = "hello"; /* Notice this variable is inside a function */
strcpy (s, "bye");
puts (s);
return 0;
}
In that case, static means something different: this creates a variable that persists across multiple calls to the same function. His other example showed a global variable, outside of a function.
EDIT:
To clarify, since you edited your question, the reason you don't want to use const char *a = "string" is you create an extra writable pointer. This means that, while you can't change the characters of the string, you can still make the pointer point to an entirely different string. See below:
const char *hello = "hello";
int main( int argc , char const *argv[] )
{
hello = "goodbye";
puts(hello);
return 0;
}
That example compiles and runs. If hello is supposed to be constant, this is surely not what you want. Of course, you can also get around this by writing this:
const char * const hello = "hello";
You still have two variables where you only needed one though -- hello is a pointer to a string constant, where if it's an array there isn't that extra pointer in the way.
Declaring it static means (if at global, file level) that it won't be visible outside this translation unit, or (if inside a scope) that it will retain its value between executions of the scope. It has nothing to do with the "constness" of the data.
While this is indeed a const string, it's neither a pointer nor a const pointer nor is the second one a declaration.
Both define (and initialize) a constant array of characters.
The only difference is that the first one will be visible and accessible from other translation units (proper declarations assumed), while the second one won't.
Note that, in C++, instead of making variables and constants static, you could put them into an unnamed namespace. Then, too, they are inaccessible from other translation units.
On the
const char *abc = "..."; and <br/>
const char def[] = "..."
part of the question...
The only difference to my knowledge is that the array-style definition is not demoted to a pointer when using the sizeof operator.
sizeof(abc) == size of pointer type <br/>
sizeof(def) == size of string (including \0)
Is it for use at a global (file) level or within a class or within a function ? The meaning of static differs ..
For a file level: It depends on the scope you want (either global or limited to the file). No other difference.
For a class: It's best with the static if you're not gonna change it. Because a const can still be redefined on the constructor so it will have to allocate space for a pointer inside the class itself if it's not static. If it is static then no need for a pointer in each class.
For a function: Doesn't really change anything important I think. In the non static case, a pointer will be allocated on the stack and initialized to point in .rodata at each function call. In the other case, it's more like a global variable but with limited scope.
Related
It is common to see the keyword const with pointers :
void function(const char *string)
{
const char *other_string = "some string";
}
But why do not we use const every time we declare a variable that we will not change ? It is rare to see :
void function(const int i)
{
const double j = 1.2;
// i and j will not be changed in this function
}
I am trying to understand why we do not use const more often, is it always a good thing to use it when we can, or not ?
This post seems to answer YES, but in reality this doest not seem to be the case ...
In most cases it no longer makes a difference.
Often enough the compiler will be able to deduce that the variable is actually read only, and treat it as a constant during optimization.
Either way, you usually use const consequently on things like const char *string in order to avoid accidentally modifying the parameter.
Since all parameters are passed by value, this isn't something which can't happen for an integer. Only for pointers the pointer itself is the value.
Actually, const char *string isn't fully constant either yet. Only the chars the pointer is pointing to is, but the pointer as a variable isn't. It would only become when specifying it as const char * const string. Now the string variable is completely constant for the scope of the function.
In the case you give, I would always say
void function(const int i)
in a situation where the role of i is to parameterise the behaviour of the function -- which is almost always. If I change i in the body of the function, I have either made an error, or written something which another person will find hard to understand later.
Intentionally modifying the value of i in the function isn't as "dangerous" as modifying a entity through its pointer -- it won't create side-effects outside the function. I guess that's why most developers don't feel the pressure to define primitive paramters as const. I maintain, however, that it is a sensible thing to do, if one cares about long-term maintenance.
In your second example, the parameter is passed by value, making it const basicly has no meaning. const is most handy when passing parameters by reference.
There is another problem with const known as "const poisoning". Consider the following:
int foo(char * str, int n)
{
...
bar(str);
...
}
If we make str to be const, we must then ensure that bar also takes a const etc. (which can affect multiple files and modules). This is especially painful if you're editing old and inconsistent code (not always the case, but should be considered).
I'm trying to learn c, so I tried reading some source code.
But I have no idea what this might mean:
static const char*(*const functab[])(void)={
ram,date
};
The first part, static const char* is fine, as it seems to be a function (has an argument of type void), static should mean that it is only visible in this file and const char* should mean that the value cannot be changed but the address can be changed.
But in that case, it doesn't make sense after the last part following the function name, as it was the case with
static const char * date(void);
static const char * ram(void);
Instead of the function name there is (*const functab[]), a const array called functab containing addresses?
Is this some kind of wrapping function containing the functions ram and date? Some alternative way of declaring arrays?
functab is an array of function pointers (array of const function pointers, to be exact), which returns const char* and accepts no arguments.
Later,
... = { ram, date };
is a brace-enclosed initializer list which serves as the initializer for the array.
This is the way to define array of function pointers in C. So instead of calling function as ram(), using this array you can call it by (* functab[1]).
Below discussion has good examples of array of function pointer:
How can I use an array of function pointers?
Short answer: Here functab is an array of function pointers, and the array is initialized with pointers to functions ram and date. This also explains the name functab which is likely from "FUNCtion TABle".
Long answer: In C you can get a pointer to a function and save it to a variable. A variable used in this fashion is known as a function pointer.
For example, funcptr variable below will contain the address of do_stuff's entry point:
int do_stuff(const char* x) { ...do stuff.. }
...
ftype_t funcptr = &do_stuff;
...
(*funcptr)("now"); // calls do_stuff()
This will only work if you have already defined the type of funcptr, which is ftype_t here. The type definition should take this form:
typedef int (*ftype_t)(const char*);
In English, this means ftype_t is being defined as a type of function that takes const char* as its only argument and returns int.
If you didn't want to typedef only for this, you could have achieved the same thing by doing below:
int (*funcptr)(const char*) = &do_stuff;
This works, but its syntax is confusing. Also it gets quite ugly if you attempt to do something like building an array of function pointers, which is exactly what your code does.
Shown below is equivalent code, which is much easier to understand:
typedef static const char*(*myfn_t)(void);
const myfn_t functab[] = { &ram, &date };
(The & (address of) is usually optional, but recommended. )
Complex variable declarations need to be read inside out in C:
functab is the identifier of the variable, so we start reading here...
functab[] it is an array...
*const functab[] of constant pointers...
(*const functab[])(...) to functions...
(*const functab[])(void) that take no arguments...
const char*(*const functab[])(void) but return a const char*.
The meaning of static depends on whether it's outside or inside of a function. If it's outside, the static means that functab is declared with file scope (i.e. a global variable that's only visible inside a single .c file). If it's inside a function, it means that functab is a global variable that's only visible inside that function.
The = { ram, date } initialize the array with two members. Both ram and date should be functions that are declared as const char* ram(void).
The effect of this declaration is, that the following function calls are equivalent:
const char* result = ram();
const char* result = functab[0]();
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
I have a program with some global strings defined at the top of the file like this:
static const char * const STRING_A = "STRING A";
static const char * const STRING_B = "STRING B";
Then in the main program loop I repeatedly call a function. This function contains a pointer which is to point to the above strings, depending on user input. By default I want it to be set to STRING_A, so what I essentially have is this:
// Called repeatedly from a loop.
void input_function()
{
static const char *current = STRING_A;
// Do stuff and reassign different strings to "current"
...
}
The problem that I have is that when compiling I get "error: initializer element is not constant". This is using GCC 4.7.2. What confuses me more is that the error goes away if I get rid of the "static" keyword in the input function. This isn't a solution though, as the static keyword is needed for the function to keep track of the current string between calls.
Obviously I could fix this in many ways, most simply by just getting rid of some of the const qualifiers. But I want to understand why this isn't working.
My current understanding is that the global string variables can't be modified to point to different strings, and neither can their individual characters be modified. The static keyword keeps them local to the source file.
For the current variable in my function my understanding is that the static keyword allows it to retain its value over multiple calls to the function, and that the const qualifier in this case means that the string pointed to by current can change - but not the characters of the string which it points to.
I'm not seeing any conflicts in those statements, so I don't understand why the compiler gives an error - particularly why it doesn't have a problem if current's "static" specifier is removed.
Thanks if someone can explain what the problem is here.
6.7.8/4 [C99]:
All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.
STRING_A is neither, hence the error.
One to way to work around this would be along the following lines:
void input_function()
{
static const char *current = NULL;
if (current == NULL) {
current = STRING_A;
}
...
}
It's because STRING_A is not a compile-time constant. Your interpretations are right however you cannot initialize a constant to be a non-constant value (such as STRING_A).
How does the compiler know what STRING_A points at while it is compiling? It doesn't -- STRING_A will point to different addresses in the read-only section of memory on each execution of program, dependant on where the string literal is in memory.
You would need to do the following to work around this restraint while pertaining the same effect:
// Defines current to be a null pointer.
static const char *current = NULL;
// Determine if current is a null pointer.
if ( current == NULL ) current = STRING_A;
gcc 4.4.4 c89
I am just wondering is it worth passing a const into a function.
i.e.
void do_something(const char *dest, const int size)
The size is a read-only so I don't want to change it. However, some developers never have this as const has it is a local copy that is being used. The pointer is const as you can change the value in the calling routine.
I always have a const on read-only local copies, as it confirms to anyone reading my code that it is a read-only variable. And also, when coding I don't make the mistake of changing it without realizing.
Many thanks for any suggestions,
People's opinion differ on this. I know some perfectly capable developers who write that const for any parameter that should not be changed locally in the function. Logically that is just consequent application of the const-correctness principle.
Whatever you do, however, you should omit the const in the function declaration in the header. The const should be part only in the function definition. C (and C++, too) has rules that make this compatible (i.e a const for a value parameter is ignored (when it affects the parameter only at its toplevel) for pure function declarations that don't have a body). The rationale is that such a const will not change anything with regard to the caller, and is thus an implementation detail of the called function.
This does not hold for your first parameter. Any capable developer i know will put that const there, because it's making an important guarantee to the caller of your function (that it won't change the data pointed to of what is passed in). The name of your parameter, however, seems a bit odd, because it indicates that the function does need to write into what is pointed to.
Notice that to be consequent, you would have to make the first parameter itself const too, like you did with the second parameter. Thus this would become (renaming it to "source" too, to avoid confusion).
void do_something(const char * const source, const int size)
Personally, I like putting const on as many variables as possible – I rarely change the value of a variable once assigned. (One notable exception are of course loop counters/iterators.)
At the very least, this significantly improves debuggability because it ensures that values cannot be changed. This makes tracking the state of the execution much easier. It also improves readability because it signals the intent of working with immutable values.
Consequently, I do the same for function parameters. After all, they behave like normal variables inside the function.
On the other hand, this confuses the hell out of many other programmers so in most collaborative projects I refrain from doing this; it would break consistency and be counter-productive.
The so called "const correctness" is very important especially if you are creating some module (dll for example) where other people will use it. It makes it much easier to understand the purpose of the function and helps prevent some odd bugs (among other things). So yes, i would definetly suggest using the const modifier where applicable.
EDIT: now looking closely at the function header, it seems that "dest" is something which the function has to change. Then declaring it as const seems odd.
In my opinion there is no point in declaring const on anything else than a pointed area. Scalar parameters (and even pointers) are local copies with the exact same constraints as other local variables. They are in fact local variables and it's sometime appropriate to use them and modify them which may avoid unecessary copies of their values.
char * strcat(char *d, const char *s)
{
char *p = d;
while(*p) p++;
while(*s) *p++ = *s++;
*p = 0;
return d;
}
char * strcat(char *d, const char *s)
{
char *p = d;
const char *s2 = s;
while(*p) p++;
while(*s2) *p++ = *s2++;
*p = 0;
return d;
}
Is the second variant really better? I don't think so.
When using the old K&R syntax it's more obvious that they are local variables of the function.
char * strcat(d, s)
char *d;
const char *s;
{
...