How Should I Define/Declare String ConstantsHow do you declare string constants in C?How do you set, clear,...

Yeshiva University RIETS Semicha Yorei and Yadin

How do we edit a novel that's written by several people?

What is Crew Dragon approaching in this picture?

What is the wife of a henpecked husband called?

Quenching swords in dragon blood; why?

Should I choose Itemized or Standard deduction?

Meaning of すきっとした

Word to be used for "standing with your toes pointing out"

What can I substitute for soda pop in a sweet pork recipe?

Metadata API deployments are failing in Spring '19

How to approximate rolls for potions of healing using only d6's?

LTSpice: When running a linear AC simulation, how to view the voltage ratio between two voltages?

Walking in a rotating spacecraft and Newton's 3rd Law of Motion

Is my plan for fixing my water heater leak bad?

Why does the DC-9-80 have this cusp in its fuselage?

How to acknowledge an embarrassing job interview, now that I work directly with the interviewer?

Finding an integral using a table?

Why is commutativity optional in multiplication for rings?

Is it a fallacy if someone claims they need an explanation for every word of your argument to the point where they don't understand common terms?

What is better: yes / no radio, or simple checkbox?

Auto Insert date into Notepad

Why do members of Congress in committee hearings ask witnesses the same question multiple times?

Which aircraft had such a luxurious-looking navigator's station?

For Loop and Sum



How Should I Define/Declare String Constants


How do you declare string constants in C?How do you set, clear, and toggle a single bit?How do function pointers in C work?What is the difference between a definition and a declaration?Improve INSERT-per-second performance of SQLite?Declaring pointers; asterisk on the left or right of the space between the type and name?What's the purpose of using braces (i.e. {}) for a single-line if or loop?Why does the C preprocessor interpret the word “linux” as the constant “1”?constant pointer and pointer to constant in a stringIs it reasonable to use enums instead of #defines for compile-time constants in C?Pointer to constant string in struct













6















I've always used string constants in C as one of the following



char *filename = "foo.txt";
const char *s = "bar"; /* preferably this or the next one */
const char *const s3 = "baz":


But, after reading this, now I'm wondering, should I be declaring my string constants as



const char s3[] = "bux";


?










share|improve this question




















  • 1





    Interesting.. The author is correct - "arrays" ARE different from "pointers". And I would have THOUGHT that the pointer syntax (e.g. const char *s = "bar";) was generally "preferred". I'm surprised with his conclusions that "array syntax" is actually more efficient - with different compilers, and on different platforms.

    – paulsm4
    3 hours ago











  • Indeed. I always used const char *s = "bar"; where I could. I never really thought to use a const-char array. I've been trying to find a solid answer for 2 days so I figured I had to ask here :P. I realize that I can use sizeof with the array version, but that isn't really too important at least in my current case. I'm wondering, with this author's considerations, what the general approach should be.

    – RastaJedi
    3 hours ago








  • 1





    Seems like a micro-optimization to me.

    – dbush
    3 hours ago











  • I had another pro-array version link I was reading, that was talking about the overhead of using the pointer version. I can't seem to find it right now but I'll post back if I do. And @dbush, I'm sure, but I don't know if I have OCD or what, but I get real picky about real mundane stuff haha.

    – RastaJedi
    3 hours ago








  • 1





    In Apple LLVM 10,0.0 with clang-1000.11.45.5, the difference vanishes if you insert const after * in const char *ptr = "Lorum ipsum";. The fact the compiler had to load ptr arose entirely from the fact it could be changed in some other module not visible to the compiler. Making the pointer const eliminates that, and the compiler can prepare the address of the string directly, without loading the pointer.

    – Eric Postpischil
    3 hours ago
















6















I've always used string constants in C as one of the following



char *filename = "foo.txt";
const char *s = "bar"; /* preferably this or the next one */
const char *const s3 = "baz":


But, after reading this, now I'm wondering, should I be declaring my string constants as



const char s3[] = "bux";


?










share|improve this question




















  • 1





    Interesting.. The author is correct - "arrays" ARE different from "pointers". And I would have THOUGHT that the pointer syntax (e.g. const char *s = "bar";) was generally "preferred". I'm surprised with his conclusions that "array syntax" is actually more efficient - with different compilers, and on different platforms.

    – paulsm4
    3 hours ago











  • Indeed. I always used const char *s = "bar"; where I could. I never really thought to use a const-char array. I've been trying to find a solid answer for 2 days so I figured I had to ask here :P. I realize that I can use sizeof with the array version, but that isn't really too important at least in my current case. I'm wondering, with this author's considerations, what the general approach should be.

    – RastaJedi
    3 hours ago








  • 1





    Seems like a micro-optimization to me.

    – dbush
    3 hours ago











  • I had another pro-array version link I was reading, that was talking about the overhead of using the pointer version. I can't seem to find it right now but I'll post back if I do. And @dbush, I'm sure, but I don't know if I have OCD or what, but I get real picky about real mundane stuff haha.

    – RastaJedi
    3 hours ago








  • 1





    In Apple LLVM 10,0.0 with clang-1000.11.45.5, the difference vanishes if you insert const after * in const char *ptr = "Lorum ipsum";. The fact the compiler had to load ptr arose entirely from the fact it could be changed in some other module not visible to the compiler. Making the pointer const eliminates that, and the compiler can prepare the address of the string directly, without loading the pointer.

    – Eric Postpischil
    3 hours ago














6












6








6


1






I've always used string constants in C as one of the following



char *filename = "foo.txt";
const char *s = "bar"; /* preferably this or the next one */
const char *const s3 = "baz":


But, after reading this, now I'm wondering, should I be declaring my string constants as



const char s3[] = "bux";


?










share|improve this question
















I've always used string constants in C as one of the following



char *filename = "foo.txt";
const char *s = "bar"; /* preferably this or the next one */
const char *const s3 = "baz":


But, after reading this, now I'm wondering, should I be declaring my string constants as



const char s3[] = "bux";


?







c






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 3 hours ago







RastaJedi

















asked 3 hours ago









RastaJediRastaJedi

4461416




4461416








  • 1





    Interesting.. The author is correct - "arrays" ARE different from "pointers". And I would have THOUGHT that the pointer syntax (e.g. const char *s = "bar";) was generally "preferred". I'm surprised with his conclusions that "array syntax" is actually more efficient - with different compilers, and on different platforms.

    – paulsm4
    3 hours ago











  • Indeed. I always used const char *s = "bar"; where I could. I never really thought to use a const-char array. I've been trying to find a solid answer for 2 days so I figured I had to ask here :P. I realize that I can use sizeof with the array version, but that isn't really too important at least in my current case. I'm wondering, with this author's considerations, what the general approach should be.

    – RastaJedi
    3 hours ago








  • 1





    Seems like a micro-optimization to me.

    – dbush
    3 hours ago











  • I had another pro-array version link I was reading, that was talking about the overhead of using the pointer version. I can't seem to find it right now but I'll post back if I do. And @dbush, I'm sure, but I don't know if I have OCD or what, but I get real picky about real mundane stuff haha.

    – RastaJedi
    3 hours ago








  • 1





    In Apple LLVM 10,0.0 with clang-1000.11.45.5, the difference vanishes if you insert const after * in const char *ptr = "Lorum ipsum";. The fact the compiler had to load ptr arose entirely from the fact it could be changed in some other module not visible to the compiler. Making the pointer const eliminates that, and the compiler can prepare the address of the string directly, without loading the pointer.

    – Eric Postpischil
    3 hours ago














  • 1





    Interesting.. The author is correct - "arrays" ARE different from "pointers". And I would have THOUGHT that the pointer syntax (e.g. const char *s = "bar";) was generally "preferred". I'm surprised with his conclusions that "array syntax" is actually more efficient - with different compilers, and on different platforms.

    – paulsm4
    3 hours ago











  • Indeed. I always used const char *s = "bar"; where I could. I never really thought to use a const-char array. I've been trying to find a solid answer for 2 days so I figured I had to ask here :P. I realize that I can use sizeof with the array version, but that isn't really too important at least in my current case. I'm wondering, with this author's considerations, what the general approach should be.

    – RastaJedi
    3 hours ago








  • 1





    Seems like a micro-optimization to me.

    – dbush
    3 hours ago











  • I had another pro-array version link I was reading, that was talking about the overhead of using the pointer version. I can't seem to find it right now but I'll post back if I do. And @dbush, I'm sure, but I don't know if I have OCD or what, but I get real picky about real mundane stuff haha.

    – RastaJedi
    3 hours ago








  • 1





    In Apple LLVM 10,0.0 with clang-1000.11.45.5, the difference vanishes if you insert const after * in const char *ptr = "Lorum ipsum";. The fact the compiler had to load ptr arose entirely from the fact it could be changed in some other module not visible to the compiler. Making the pointer const eliminates that, and the compiler can prepare the address of the string directly, without loading the pointer.

    – Eric Postpischil
    3 hours ago








1




1





Interesting.. The author is correct - "arrays" ARE different from "pointers". And I would have THOUGHT that the pointer syntax (e.g. const char *s = "bar";) was generally "preferred". I'm surprised with his conclusions that "array syntax" is actually more efficient - with different compilers, and on different platforms.

– paulsm4
3 hours ago





Interesting.. The author is correct - "arrays" ARE different from "pointers". And I would have THOUGHT that the pointer syntax (e.g. const char *s = "bar";) was generally "preferred". I'm surprised with his conclusions that "array syntax" is actually more efficient - with different compilers, and on different platforms.

– paulsm4
3 hours ago













Indeed. I always used const char *s = "bar"; where I could. I never really thought to use a const-char array. I've been trying to find a solid answer for 2 days so I figured I had to ask here :P. I realize that I can use sizeof with the array version, but that isn't really too important at least in my current case. I'm wondering, with this author's considerations, what the general approach should be.

– RastaJedi
3 hours ago







Indeed. I always used const char *s = "bar"; where I could. I never really thought to use a const-char array. I've been trying to find a solid answer for 2 days so I figured I had to ask here :P. I realize that I can use sizeof with the array version, but that isn't really too important at least in my current case. I'm wondering, with this author's considerations, what the general approach should be.

– RastaJedi
3 hours ago






1




1





Seems like a micro-optimization to me.

– dbush
3 hours ago





Seems like a micro-optimization to me.

– dbush
3 hours ago













I had another pro-array version link I was reading, that was talking about the overhead of using the pointer version. I can't seem to find it right now but I'll post back if I do. And @dbush, I'm sure, but I don't know if I have OCD or what, but I get real picky about real mundane stuff haha.

– RastaJedi
3 hours ago







I had another pro-array version link I was reading, that was talking about the overhead of using the pointer version. I can't seem to find it right now but I'll post back if I do. And @dbush, I'm sure, but I don't know if I have OCD or what, but I get real picky about real mundane stuff haha.

– RastaJedi
3 hours ago






1




1





In Apple LLVM 10,0.0 with clang-1000.11.45.5, the difference vanishes if you insert const after * in const char *ptr = "Lorum ipsum";. The fact the compiler had to load ptr arose entirely from the fact it could be changed in some other module not visible to the compiler. Making the pointer const eliminates that, and the compiler can prepare the address of the string directly, without loading the pointer.

– Eric Postpischil
3 hours ago





In Apple LLVM 10,0.0 with clang-1000.11.45.5, the difference vanishes if you insert const after * in const char *ptr = "Lorum ipsum";. The fact the compiler had to load ptr arose entirely from the fact it could be changed in some other module not visible to the compiler. Making the pointer const eliminates that, and the compiler can prepare the address of the string directly, without loading the pointer.

– Eric Postpischil
3 hours ago












3 Answers
3






active

oldest

votes


















3














Pointer and arrays are different. Defining string constants as pointers or arrays fits different purposes.



When you define a global string constant that is not subject to change, I would recommend you make it a const array:



const char product_name[] = "The program version 3";


Defining it as const char *product_name = "The program version 3"; actually defines 2 objects: the string constant itself, which will reside in a constant segment, and the pointer which can be changed to point to another string or set to NULL.



Conversely, defining a string constant as a local variable would be better done as a local pointer variable of type const char *, initialized with the address of a string constant:



int main() {
const char *s1 = "world";
printf("Hello %sn", s1);
return 0;
}


If you define this one as an array, depending on the compiler and usage inside the function, the code will make space for the array on the stack and initialize it by copying the string constant into it, a more costly operation for long strings.



Note also that const char const *s3 = "baz"; is a redundant form of const char *s3 = "baz";. It is different from const char * const s3 = "baz"; which defines a constant pointer to a constant array of characters.



Finally, string constants are immutable and as such should have type const char []. The C Standard purposely allows programmers to store their addresses into non const pointers as in char *s2 = "hello"; to avoid producing warnings for legacy code. In new code, it is highly advisable to always use const char * pointers to manipulate string constants. This may force you to declare function arguments as const char * when the function does not change the string contents. This process is known as constification and avoid subtile bugs.



Note that some functions violate this const propagation: strchr() does not modify the string received, declared as const char *, but returns a char *. It is therefore possible to store a pointer to a string constant into a plain char * pointer this way:



char *p = strchr("Hello Worldn", 'H');


This problem is solved in C++ via overloading. C programmers must deal with this as a shortcoming. An even more annoying situation is that of strtol() where the address of a char * is passed and a cast is required to preserve proper constness .






share|improve this answer


























  • Sorry, const char *const s3 is what I meant to type. Fixed it now :). So for global, using the array version won't result in a copy?

    – RastaJedi
    3 hours ago













  • To the extent that you would get a "redundant" pointer variable in the s1 case, aren't you prone to a "redundant" array copy in the product_name case (for them's the semantics) which is far worse? I've never heard this advice before tbh.

    – Lightness Races in Orbit
    3 hours ago











  • @LightnessRacesinOrbit: in the case of a global variable, the is no copy at runtime but indeed the string constant may be duplicated in the binary file and in memory: const char *s1 = "toto", *s2 = "toto"; may initialize both s1 and s2 to the same value whereas const char s1[] = "toto", s2[] = "toto"; defines 2 separate objects each with the same duplicated contents.

    – chqrlie
    2 hours ago













  • Right, and doesn't that suggest that const char* is a much superior choice?

    – Lightness Races in Orbit
    2 hours ago






  • 1





    I've marked this as the accepted answer because this answers my 'how should I declare' question more directly, although the information in @EricPostpischil's answer directly comments on the information provided in my source link. Unfortunately I cannot accept two answers, but I urge all of you who are reading this answer to also view his answer. Thank you all!

    – RastaJedi
    2 hours ago



















2














The linked article explores a small artificial situation, and the difference demonstrated vanishes if you insert const after * in const char *ptr = "Lorum ipsum"; (tested in Apple LLVM 10.0.0 with clang-1000.11.45.5).



The fact the compiler had to load ptr arose entirely from the fact it could be changed in some other module not visible to the compiler. Making the pointer const eliminates that, and the compiler can prepare the address of the string directly, without loading the pointer.



If you are going to declare a pointer to a string and never change the pointer, then declare it as static const char * const ptr = "string";, and the compiler can happily provide the address of the string whenever the value of ptr is used. It does not need to actually load the contents of ptr from memory, since it can never change and will be known to point to wherever the compiler chooses to store the string. This is then the same as static const char array[] = "string";—whenever the address of the array is needed, the compiler can provide it from its knowledge of where it chose to store the array.



Furthermore, with the static specifier, ptr cannot be known outside the translation unit (the file being compiled), so the compiler can remove it during optimization (as long as you have not taken its address, perhaps when passing it to another routine outside the translation unit). The result should be no differences between the pointer method and the array method.



Rule of thumb: Tell the compiler as much as you know about stuff: If it will never change, mark it const. If it is local to the current module, mark it static. The more information the compiler has, the more it can optimize.






share|improve this answer
























  • static would only help for global scope or inside of main(), but not any other function scope? Or should I still use static in main()? If, e.g. I was using a string constant for a filename, and I was to call my own function to open up that file, it shouldn't matter if it's static even if that function was in another file (unless I was passing the address of it)... or am I mixing this up. I've never really used static much, to be honest.

    – RastaJedi
    3 hours ago











  • @RastaJedi: At file scope (outside of any function), static essentially just changes whether the thing may be known outside the current translation unit. Inside a block (any set of statements in braces in a function, main or other), static both says “this name is not known outside this block” and “this thing sticks around for all of program execution, not just block execution.” With a const object, though, the two lifetimes (static and automatic) often optimize to the same thing. (Taking addresses of things can change that, for semantic reasons, but simple uses are unaffected.)

    – Eric Postpischil
    3 hours ago











  • So if I have a static string constant, and pass it to a routine in another TLU, this would still work, but the possibility of optimization goes away, is what you are getting at? Within a function, try to mark it static if I don't need to change it anywhere else or pass it to any other routine, for a possibility of optimization? What about the cases of non-constant values. Just use static if I need it's value to stick around when it goes out of scope or to limit to that TLU within file scope? I'm assuming there's no possibility of it being optimized in this way if it is modifiable.

    – RastaJedi
    2 hours ago











  • Given static const char * const ptr = "string"; at function level, passing ptr to a routine outside the current translation unit should have the same effect as passing "string" or array, where array is const char array[] = "string";. In all those cases, the compiler only needs to pass the address of the actual string, which itself may not be changed. So it should produce the same code for all of them. If you passed &ptr outside the module, then the compiler has to create an actual ptr so it can take its address. But that is a different use case.

    – Eric Postpischil
    2 hours ago











  • Outside a function, mark anything static if it does not need to be known outside the current translation unit. Inside a function (or block), identifiers are already not known outside the function (or block), as if they were static. There, using static actually adds a property that they persist for program execution instead of function/block execution, so do not use static inside a function/block unless you need that property.

    – Eric Postpischil
    2 hours ago



















1














From the performance perspective, this is a fairly small optimization which makes sense for low-level code that needs to run with the lowest possible latency.



However, I would argue that const char s3[] = "bux"; is better from the semantic perspective, because the type of the right hand side is closer to type of the left hand side. For that reason, I think it makes sense to declare string constants with the array syntax.






share|improve this answer





















  • 1





    Aren't string literals in C not technically const-qualified type? Despite being immutable. Or you just meant the array aspect of it perhaps. Also doesn't the array version have to copy an entire string?

    – RastaJedi
    3 hours ago













  • You are correct. However, it's UB to modify the elements of a string literal, and I was referring to the array part. :)

    – merlin2011
    3 hours ago











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54975623%2fhow-should-i-define-declare-string-constants%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes









3














Pointer and arrays are different. Defining string constants as pointers or arrays fits different purposes.



When you define a global string constant that is not subject to change, I would recommend you make it a const array:



const char product_name[] = "The program version 3";


Defining it as const char *product_name = "The program version 3"; actually defines 2 objects: the string constant itself, which will reside in a constant segment, and the pointer which can be changed to point to another string or set to NULL.



Conversely, defining a string constant as a local variable would be better done as a local pointer variable of type const char *, initialized with the address of a string constant:



int main() {
const char *s1 = "world";
printf("Hello %sn", s1);
return 0;
}


If you define this one as an array, depending on the compiler and usage inside the function, the code will make space for the array on the stack and initialize it by copying the string constant into it, a more costly operation for long strings.



Note also that const char const *s3 = "baz"; is a redundant form of const char *s3 = "baz";. It is different from const char * const s3 = "baz"; which defines a constant pointer to a constant array of characters.



Finally, string constants are immutable and as such should have type const char []. The C Standard purposely allows programmers to store their addresses into non const pointers as in char *s2 = "hello"; to avoid producing warnings for legacy code. In new code, it is highly advisable to always use const char * pointers to manipulate string constants. This may force you to declare function arguments as const char * when the function does not change the string contents. This process is known as constification and avoid subtile bugs.



Note that some functions violate this const propagation: strchr() does not modify the string received, declared as const char *, but returns a char *. It is therefore possible to store a pointer to a string constant into a plain char * pointer this way:



char *p = strchr("Hello Worldn", 'H');


This problem is solved in C++ via overloading. C programmers must deal with this as a shortcoming. An even more annoying situation is that of strtol() where the address of a char * is passed and a cast is required to preserve proper constness .






share|improve this answer


























  • Sorry, const char *const s3 is what I meant to type. Fixed it now :). So for global, using the array version won't result in a copy?

    – RastaJedi
    3 hours ago













  • To the extent that you would get a "redundant" pointer variable in the s1 case, aren't you prone to a "redundant" array copy in the product_name case (for them's the semantics) which is far worse? I've never heard this advice before tbh.

    – Lightness Races in Orbit
    3 hours ago











  • @LightnessRacesinOrbit: in the case of a global variable, the is no copy at runtime but indeed the string constant may be duplicated in the binary file and in memory: const char *s1 = "toto", *s2 = "toto"; may initialize both s1 and s2 to the same value whereas const char s1[] = "toto", s2[] = "toto"; defines 2 separate objects each with the same duplicated contents.

    – chqrlie
    2 hours ago













  • Right, and doesn't that suggest that const char* is a much superior choice?

    – Lightness Races in Orbit
    2 hours ago






  • 1





    I've marked this as the accepted answer because this answers my 'how should I declare' question more directly, although the information in @EricPostpischil's answer directly comments on the information provided in my source link. Unfortunately I cannot accept two answers, but I urge all of you who are reading this answer to also view his answer. Thank you all!

    – RastaJedi
    2 hours ago
















3














Pointer and arrays are different. Defining string constants as pointers or arrays fits different purposes.



When you define a global string constant that is not subject to change, I would recommend you make it a const array:



const char product_name[] = "The program version 3";


Defining it as const char *product_name = "The program version 3"; actually defines 2 objects: the string constant itself, which will reside in a constant segment, and the pointer which can be changed to point to another string or set to NULL.



Conversely, defining a string constant as a local variable would be better done as a local pointer variable of type const char *, initialized with the address of a string constant:



int main() {
const char *s1 = "world";
printf("Hello %sn", s1);
return 0;
}


If you define this one as an array, depending on the compiler and usage inside the function, the code will make space for the array on the stack and initialize it by copying the string constant into it, a more costly operation for long strings.



Note also that const char const *s3 = "baz"; is a redundant form of const char *s3 = "baz";. It is different from const char * const s3 = "baz"; which defines a constant pointer to a constant array of characters.



Finally, string constants are immutable and as such should have type const char []. The C Standard purposely allows programmers to store their addresses into non const pointers as in char *s2 = "hello"; to avoid producing warnings for legacy code. In new code, it is highly advisable to always use const char * pointers to manipulate string constants. This may force you to declare function arguments as const char * when the function does not change the string contents. This process is known as constification and avoid subtile bugs.



Note that some functions violate this const propagation: strchr() does not modify the string received, declared as const char *, but returns a char *. It is therefore possible to store a pointer to a string constant into a plain char * pointer this way:



char *p = strchr("Hello Worldn", 'H');


This problem is solved in C++ via overloading. C programmers must deal with this as a shortcoming. An even more annoying situation is that of strtol() where the address of a char * is passed and a cast is required to preserve proper constness .






share|improve this answer


























  • Sorry, const char *const s3 is what I meant to type. Fixed it now :). So for global, using the array version won't result in a copy?

    – RastaJedi
    3 hours ago













  • To the extent that you would get a "redundant" pointer variable in the s1 case, aren't you prone to a "redundant" array copy in the product_name case (for them's the semantics) which is far worse? I've never heard this advice before tbh.

    – Lightness Races in Orbit
    3 hours ago











  • @LightnessRacesinOrbit: in the case of a global variable, the is no copy at runtime but indeed the string constant may be duplicated in the binary file and in memory: const char *s1 = "toto", *s2 = "toto"; may initialize both s1 and s2 to the same value whereas const char s1[] = "toto", s2[] = "toto"; defines 2 separate objects each with the same duplicated contents.

    – chqrlie
    2 hours ago













  • Right, and doesn't that suggest that const char* is a much superior choice?

    – Lightness Races in Orbit
    2 hours ago






  • 1





    I've marked this as the accepted answer because this answers my 'how should I declare' question more directly, although the information in @EricPostpischil's answer directly comments on the information provided in my source link. Unfortunately I cannot accept two answers, but I urge all of you who are reading this answer to also view his answer. Thank you all!

    – RastaJedi
    2 hours ago














3












3








3







Pointer and arrays are different. Defining string constants as pointers or arrays fits different purposes.



When you define a global string constant that is not subject to change, I would recommend you make it a const array:



const char product_name[] = "The program version 3";


Defining it as const char *product_name = "The program version 3"; actually defines 2 objects: the string constant itself, which will reside in a constant segment, and the pointer which can be changed to point to another string or set to NULL.



Conversely, defining a string constant as a local variable would be better done as a local pointer variable of type const char *, initialized with the address of a string constant:



int main() {
const char *s1 = "world";
printf("Hello %sn", s1);
return 0;
}


If you define this one as an array, depending on the compiler and usage inside the function, the code will make space for the array on the stack and initialize it by copying the string constant into it, a more costly operation for long strings.



Note also that const char const *s3 = "baz"; is a redundant form of const char *s3 = "baz";. It is different from const char * const s3 = "baz"; which defines a constant pointer to a constant array of characters.



Finally, string constants are immutable and as such should have type const char []. The C Standard purposely allows programmers to store their addresses into non const pointers as in char *s2 = "hello"; to avoid producing warnings for legacy code. In new code, it is highly advisable to always use const char * pointers to manipulate string constants. This may force you to declare function arguments as const char * when the function does not change the string contents. This process is known as constification and avoid subtile bugs.



Note that some functions violate this const propagation: strchr() does not modify the string received, declared as const char *, but returns a char *. It is therefore possible to store a pointer to a string constant into a plain char * pointer this way:



char *p = strchr("Hello Worldn", 'H');


This problem is solved in C++ via overloading. C programmers must deal with this as a shortcoming. An even more annoying situation is that of strtol() where the address of a char * is passed and a cast is required to preserve proper constness .






share|improve this answer















Pointer and arrays are different. Defining string constants as pointers or arrays fits different purposes.



When you define a global string constant that is not subject to change, I would recommend you make it a const array:



const char product_name[] = "The program version 3";


Defining it as const char *product_name = "The program version 3"; actually defines 2 objects: the string constant itself, which will reside in a constant segment, and the pointer which can be changed to point to another string or set to NULL.



Conversely, defining a string constant as a local variable would be better done as a local pointer variable of type const char *, initialized with the address of a string constant:



int main() {
const char *s1 = "world";
printf("Hello %sn", s1);
return 0;
}


If you define this one as an array, depending on the compiler and usage inside the function, the code will make space for the array on the stack and initialize it by copying the string constant into it, a more costly operation for long strings.



Note also that const char const *s3 = "baz"; is a redundant form of const char *s3 = "baz";. It is different from const char * const s3 = "baz"; which defines a constant pointer to a constant array of characters.



Finally, string constants are immutable and as such should have type const char []. The C Standard purposely allows programmers to store their addresses into non const pointers as in char *s2 = "hello"; to avoid producing warnings for legacy code. In new code, it is highly advisable to always use const char * pointers to manipulate string constants. This may force you to declare function arguments as const char * when the function does not change the string contents. This process is known as constification and avoid subtile bugs.



Note that some functions violate this const propagation: strchr() does not modify the string received, declared as const char *, but returns a char *. It is therefore possible to store a pointer to a string constant into a plain char * pointer this way:



char *p = strchr("Hello Worldn", 'H');


This problem is solved in C++ via overloading. C programmers must deal with this as a shortcoming. An even more annoying situation is that of strtol() where the address of a char * is passed and a cast is required to preserve proper constness .







share|improve this answer














share|improve this answer



share|improve this answer








edited 2 hours ago

























answered 3 hours ago









chqrliechqrlie

60.5k747102




60.5k747102













  • Sorry, const char *const s3 is what I meant to type. Fixed it now :). So for global, using the array version won't result in a copy?

    – RastaJedi
    3 hours ago













  • To the extent that you would get a "redundant" pointer variable in the s1 case, aren't you prone to a "redundant" array copy in the product_name case (for them's the semantics) which is far worse? I've never heard this advice before tbh.

    – Lightness Races in Orbit
    3 hours ago











  • @LightnessRacesinOrbit: in the case of a global variable, the is no copy at runtime but indeed the string constant may be duplicated in the binary file and in memory: const char *s1 = "toto", *s2 = "toto"; may initialize both s1 and s2 to the same value whereas const char s1[] = "toto", s2[] = "toto"; defines 2 separate objects each with the same duplicated contents.

    – chqrlie
    2 hours ago













  • Right, and doesn't that suggest that const char* is a much superior choice?

    – Lightness Races in Orbit
    2 hours ago






  • 1





    I've marked this as the accepted answer because this answers my 'how should I declare' question more directly, although the information in @EricPostpischil's answer directly comments on the information provided in my source link. Unfortunately I cannot accept two answers, but I urge all of you who are reading this answer to also view his answer. Thank you all!

    – RastaJedi
    2 hours ago



















  • Sorry, const char *const s3 is what I meant to type. Fixed it now :). So for global, using the array version won't result in a copy?

    – RastaJedi
    3 hours ago













  • To the extent that you would get a "redundant" pointer variable in the s1 case, aren't you prone to a "redundant" array copy in the product_name case (for them's the semantics) which is far worse? I've never heard this advice before tbh.

    – Lightness Races in Orbit
    3 hours ago











  • @LightnessRacesinOrbit: in the case of a global variable, the is no copy at runtime but indeed the string constant may be duplicated in the binary file and in memory: const char *s1 = "toto", *s2 = "toto"; may initialize both s1 and s2 to the same value whereas const char s1[] = "toto", s2[] = "toto"; defines 2 separate objects each with the same duplicated contents.

    – chqrlie
    2 hours ago













  • Right, and doesn't that suggest that const char* is a much superior choice?

    – Lightness Races in Orbit
    2 hours ago






  • 1





    I've marked this as the accepted answer because this answers my 'how should I declare' question more directly, although the information in @EricPostpischil's answer directly comments on the information provided in my source link. Unfortunately I cannot accept two answers, but I urge all of you who are reading this answer to also view his answer. Thank you all!

    – RastaJedi
    2 hours ago

















Sorry, const char *const s3 is what I meant to type. Fixed it now :). So for global, using the array version won't result in a copy?

– RastaJedi
3 hours ago







Sorry, const char *const s3 is what I meant to type. Fixed it now :). So for global, using the array version won't result in a copy?

– RastaJedi
3 hours ago















To the extent that you would get a "redundant" pointer variable in the s1 case, aren't you prone to a "redundant" array copy in the product_name case (for them's the semantics) which is far worse? I've never heard this advice before tbh.

– Lightness Races in Orbit
3 hours ago





To the extent that you would get a "redundant" pointer variable in the s1 case, aren't you prone to a "redundant" array copy in the product_name case (for them's the semantics) which is far worse? I've never heard this advice before tbh.

– Lightness Races in Orbit
3 hours ago













@LightnessRacesinOrbit: in the case of a global variable, the is no copy at runtime but indeed the string constant may be duplicated in the binary file and in memory: const char *s1 = "toto", *s2 = "toto"; may initialize both s1 and s2 to the same value whereas const char s1[] = "toto", s2[] = "toto"; defines 2 separate objects each with the same duplicated contents.

– chqrlie
2 hours ago







@LightnessRacesinOrbit: in the case of a global variable, the is no copy at runtime but indeed the string constant may be duplicated in the binary file and in memory: const char *s1 = "toto", *s2 = "toto"; may initialize both s1 and s2 to the same value whereas const char s1[] = "toto", s2[] = "toto"; defines 2 separate objects each with the same duplicated contents.

– chqrlie
2 hours ago















Right, and doesn't that suggest that const char* is a much superior choice?

– Lightness Races in Orbit
2 hours ago





Right, and doesn't that suggest that const char* is a much superior choice?

– Lightness Races in Orbit
2 hours ago




1




1





I've marked this as the accepted answer because this answers my 'how should I declare' question more directly, although the information in @EricPostpischil's answer directly comments on the information provided in my source link. Unfortunately I cannot accept two answers, but I urge all of you who are reading this answer to also view his answer. Thank you all!

– RastaJedi
2 hours ago





I've marked this as the accepted answer because this answers my 'how should I declare' question more directly, although the information in @EricPostpischil's answer directly comments on the information provided in my source link. Unfortunately I cannot accept two answers, but I urge all of you who are reading this answer to also view his answer. Thank you all!

– RastaJedi
2 hours ago













2














The linked article explores a small artificial situation, and the difference demonstrated vanishes if you insert const after * in const char *ptr = "Lorum ipsum"; (tested in Apple LLVM 10.0.0 with clang-1000.11.45.5).



The fact the compiler had to load ptr arose entirely from the fact it could be changed in some other module not visible to the compiler. Making the pointer const eliminates that, and the compiler can prepare the address of the string directly, without loading the pointer.



If you are going to declare a pointer to a string and never change the pointer, then declare it as static const char * const ptr = "string";, and the compiler can happily provide the address of the string whenever the value of ptr is used. It does not need to actually load the contents of ptr from memory, since it can never change and will be known to point to wherever the compiler chooses to store the string. This is then the same as static const char array[] = "string";—whenever the address of the array is needed, the compiler can provide it from its knowledge of where it chose to store the array.



Furthermore, with the static specifier, ptr cannot be known outside the translation unit (the file being compiled), so the compiler can remove it during optimization (as long as you have not taken its address, perhaps when passing it to another routine outside the translation unit). The result should be no differences between the pointer method and the array method.



Rule of thumb: Tell the compiler as much as you know about stuff: If it will never change, mark it const. If it is local to the current module, mark it static. The more information the compiler has, the more it can optimize.






share|improve this answer
























  • static would only help for global scope or inside of main(), but not any other function scope? Or should I still use static in main()? If, e.g. I was using a string constant for a filename, and I was to call my own function to open up that file, it shouldn't matter if it's static even if that function was in another file (unless I was passing the address of it)... or am I mixing this up. I've never really used static much, to be honest.

    – RastaJedi
    3 hours ago











  • @RastaJedi: At file scope (outside of any function), static essentially just changes whether the thing may be known outside the current translation unit. Inside a block (any set of statements in braces in a function, main or other), static both says “this name is not known outside this block” and “this thing sticks around for all of program execution, not just block execution.” With a const object, though, the two lifetimes (static and automatic) often optimize to the same thing. (Taking addresses of things can change that, for semantic reasons, but simple uses are unaffected.)

    – Eric Postpischil
    3 hours ago











  • So if I have a static string constant, and pass it to a routine in another TLU, this would still work, but the possibility of optimization goes away, is what you are getting at? Within a function, try to mark it static if I don't need to change it anywhere else or pass it to any other routine, for a possibility of optimization? What about the cases of non-constant values. Just use static if I need it's value to stick around when it goes out of scope or to limit to that TLU within file scope? I'm assuming there's no possibility of it being optimized in this way if it is modifiable.

    – RastaJedi
    2 hours ago











  • Given static const char * const ptr = "string"; at function level, passing ptr to a routine outside the current translation unit should have the same effect as passing "string" or array, where array is const char array[] = "string";. In all those cases, the compiler only needs to pass the address of the actual string, which itself may not be changed. So it should produce the same code for all of them. If you passed &ptr outside the module, then the compiler has to create an actual ptr so it can take its address. But that is a different use case.

    – Eric Postpischil
    2 hours ago











  • Outside a function, mark anything static if it does not need to be known outside the current translation unit. Inside a function (or block), identifiers are already not known outside the function (or block), as if they were static. There, using static actually adds a property that they persist for program execution instead of function/block execution, so do not use static inside a function/block unless you need that property.

    – Eric Postpischil
    2 hours ago
















2














The linked article explores a small artificial situation, and the difference demonstrated vanishes if you insert const after * in const char *ptr = "Lorum ipsum"; (tested in Apple LLVM 10.0.0 with clang-1000.11.45.5).



The fact the compiler had to load ptr arose entirely from the fact it could be changed in some other module not visible to the compiler. Making the pointer const eliminates that, and the compiler can prepare the address of the string directly, without loading the pointer.



If you are going to declare a pointer to a string and never change the pointer, then declare it as static const char * const ptr = "string";, and the compiler can happily provide the address of the string whenever the value of ptr is used. It does not need to actually load the contents of ptr from memory, since it can never change and will be known to point to wherever the compiler chooses to store the string. This is then the same as static const char array[] = "string";—whenever the address of the array is needed, the compiler can provide it from its knowledge of where it chose to store the array.



Furthermore, with the static specifier, ptr cannot be known outside the translation unit (the file being compiled), so the compiler can remove it during optimization (as long as you have not taken its address, perhaps when passing it to another routine outside the translation unit). The result should be no differences between the pointer method and the array method.



Rule of thumb: Tell the compiler as much as you know about stuff: If it will never change, mark it const. If it is local to the current module, mark it static. The more information the compiler has, the more it can optimize.






share|improve this answer
























  • static would only help for global scope or inside of main(), but not any other function scope? Or should I still use static in main()? If, e.g. I was using a string constant for a filename, and I was to call my own function to open up that file, it shouldn't matter if it's static even if that function was in another file (unless I was passing the address of it)... or am I mixing this up. I've never really used static much, to be honest.

    – RastaJedi
    3 hours ago











  • @RastaJedi: At file scope (outside of any function), static essentially just changes whether the thing may be known outside the current translation unit. Inside a block (any set of statements in braces in a function, main or other), static both says “this name is not known outside this block” and “this thing sticks around for all of program execution, not just block execution.” With a const object, though, the two lifetimes (static and automatic) often optimize to the same thing. (Taking addresses of things can change that, for semantic reasons, but simple uses are unaffected.)

    – Eric Postpischil
    3 hours ago











  • So if I have a static string constant, and pass it to a routine in another TLU, this would still work, but the possibility of optimization goes away, is what you are getting at? Within a function, try to mark it static if I don't need to change it anywhere else or pass it to any other routine, for a possibility of optimization? What about the cases of non-constant values. Just use static if I need it's value to stick around when it goes out of scope or to limit to that TLU within file scope? I'm assuming there's no possibility of it being optimized in this way if it is modifiable.

    – RastaJedi
    2 hours ago











  • Given static const char * const ptr = "string"; at function level, passing ptr to a routine outside the current translation unit should have the same effect as passing "string" or array, where array is const char array[] = "string";. In all those cases, the compiler only needs to pass the address of the actual string, which itself may not be changed. So it should produce the same code for all of them. If you passed &ptr outside the module, then the compiler has to create an actual ptr so it can take its address. But that is a different use case.

    – Eric Postpischil
    2 hours ago











  • Outside a function, mark anything static if it does not need to be known outside the current translation unit. Inside a function (or block), identifiers are already not known outside the function (or block), as if they were static. There, using static actually adds a property that they persist for program execution instead of function/block execution, so do not use static inside a function/block unless you need that property.

    – Eric Postpischil
    2 hours ago














2












2








2







The linked article explores a small artificial situation, and the difference demonstrated vanishes if you insert const after * in const char *ptr = "Lorum ipsum"; (tested in Apple LLVM 10.0.0 with clang-1000.11.45.5).



The fact the compiler had to load ptr arose entirely from the fact it could be changed in some other module not visible to the compiler. Making the pointer const eliminates that, and the compiler can prepare the address of the string directly, without loading the pointer.



If you are going to declare a pointer to a string and never change the pointer, then declare it as static const char * const ptr = "string";, and the compiler can happily provide the address of the string whenever the value of ptr is used. It does not need to actually load the contents of ptr from memory, since it can never change and will be known to point to wherever the compiler chooses to store the string. This is then the same as static const char array[] = "string";—whenever the address of the array is needed, the compiler can provide it from its knowledge of where it chose to store the array.



Furthermore, with the static specifier, ptr cannot be known outside the translation unit (the file being compiled), so the compiler can remove it during optimization (as long as you have not taken its address, perhaps when passing it to another routine outside the translation unit). The result should be no differences between the pointer method and the array method.



Rule of thumb: Tell the compiler as much as you know about stuff: If it will never change, mark it const. If it is local to the current module, mark it static. The more information the compiler has, the more it can optimize.






share|improve this answer













The linked article explores a small artificial situation, and the difference demonstrated vanishes if you insert const after * in const char *ptr = "Lorum ipsum"; (tested in Apple LLVM 10.0.0 with clang-1000.11.45.5).



The fact the compiler had to load ptr arose entirely from the fact it could be changed in some other module not visible to the compiler. Making the pointer const eliminates that, and the compiler can prepare the address of the string directly, without loading the pointer.



If you are going to declare a pointer to a string and never change the pointer, then declare it as static const char * const ptr = "string";, and the compiler can happily provide the address of the string whenever the value of ptr is used. It does not need to actually load the contents of ptr from memory, since it can never change and will be known to point to wherever the compiler chooses to store the string. This is then the same as static const char array[] = "string";—whenever the address of the array is needed, the compiler can provide it from its knowledge of where it chose to store the array.



Furthermore, with the static specifier, ptr cannot be known outside the translation unit (the file being compiled), so the compiler can remove it during optimization (as long as you have not taken its address, perhaps when passing it to another routine outside the translation unit). The result should be no differences between the pointer method and the array method.



Rule of thumb: Tell the compiler as much as you know about stuff: If it will never change, mark it const. If it is local to the current module, mark it static. The more information the compiler has, the more it can optimize.







share|improve this answer












share|improve this answer



share|improve this answer










answered 3 hours ago









Eric PostpischilEric Postpischil

77.7k883165




77.7k883165













  • static would only help for global scope or inside of main(), but not any other function scope? Or should I still use static in main()? If, e.g. I was using a string constant for a filename, and I was to call my own function to open up that file, it shouldn't matter if it's static even if that function was in another file (unless I was passing the address of it)... or am I mixing this up. I've never really used static much, to be honest.

    – RastaJedi
    3 hours ago











  • @RastaJedi: At file scope (outside of any function), static essentially just changes whether the thing may be known outside the current translation unit. Inside a block (any set of statements in braces in a function, main or other), static both says “this name is not known outside this block” and “this thing sticks around for all of program execution, not just block execution.” With a const object, though, the two lifetimes (static and automatic) often optimize to the same thing. (Taking addresses of things can change that, for semantic reasons, but simple uses are unaffected.)

    – Eric Postpischil
    3 hours ago











  • So if I have a static string constant, and pass it to a routine in another TLU, this would still work, but the possibility of optimization goes away, is what you are getting at? Within a function, try to mark it static if I don't need to change it anywhere else or pass it to any other routine, for a possibility of optimization? What about the cases of non-constant values. Just use static if I need it's value to stick around when it goes out of scope or to limit to that TLU within file scope? I'm assuming there's no possibility of it being optimized in this way if it is modifiable.

    – RastaJedi
    2 hours ago











  • Given static const char * const ptr = "string"; at function level, passing ptr to a routine outside the current translation unit should have the same effect as passing "string" or array, where array is const char array[] = "string";. In all those cases, the compiler only needs to pass the address of the actual string, which itself may not be changed. So it should produce the same code for all of them. If you passed &ptr outside the module, then the compiler has to create an actual ptr so it can take its address. But that is a different use case.

    – Eric Postpischil
    2 hours ago











  • Outside a function, mark anything static if it does not need to be known outside the current translation unit. Inside a function (or block), identifiers are already not known outside the function (or block), as if they were static. There, using static actually adds a property that they persist for program execution instead of function/block execution, so do not use static inside a function/block unless you need that property.

    – Eric Postpischil
    2 hours ago



















  • static would only help for global scope or inside of main(), but not any other function scope? Or should I still use static in main()? If, e.g. I was using a string constant for a filename, and I was to call my own function to open up that file, it shouldn't matter if it's static even if that function was in another file (unless I was passing the address of it)... or am I mixing this up. I've never really used static much, to be honest.

    – RastaJedi
    3 hours ago











  • @RastaJedi: At file scope (outside of any function), static essentially just changes whether the thing may be known outside the current translation unit. Inside a block (any set of statements in braces in a function, main or other), static both says “this name is not known outside this block” and “this thing sticks around for all of program execution, not just block execution.” With a const object, though, the two lifetimes (static and automatic) often optimize to the same thing. (Taking addresses of things can change that, for semantic reasons, but simple uses are unaffected.)

    – Eric Postpischil
    3 hours ago











  • So if I have a static string constant, and pass it to a routine in another TLU, this would still work, but the possibility of optimization goes away, is what you are getting at? Within a function, try to mark it static if I don't need to change it anywhere else or pass it to any other routine, for a possibility of optimization? What about the cases of non-constant values. Just use static if I need it's value to stick around when it goes out of scope or to limit to that TLU within file scope? I'm assuming there's no possibility of it being optimized in this way if it is modifiable.

    – RastaJedi
    2 hours ago











  • Given static const char * const ptr = "string"; at function level, passing ptr to a routine outside the current translation unit should have the same effect as passing "string" or array, where array is const char array[] = "string";. In all those cases, the compiler only needs to pass the address of the actual string, which itself may not be changed. So it should produce the same code for all of them. If you passed &ptr outside the module, then the compiler has to create an actual ptr so it can take its address. But that is a different use case.

    – Eric Postpischil
    2 hours ago











  • Outside a function, mark anything static if it does not need to be known outside the current translation unit. Inside a function (or block), identifiers are already not known outside the function (or block), as if they were static. There, using static actually adds a property that they persist for program execution instead of function/block execution, so do not use static inside a function/block unless you need that property.

    – Eric Postpischil
    2 hours ago

















static would only help for global scope or inside of main(), but not any other function scope? Or should I still use static in main()? If, e.g. I was using a string constant for a filename, and I was to call my own function to open up that file, it shouldn't matter if it's static even if that function was in another file (unless I was passing the address of it)... or am I mixing this up. I've never really used static much, to be honest.

– RastaJedi
3 hours ago





static would only help for global scope or inside of main(), but not any other function scope? Or should I still use static in main()? If, e.g. I was using a string constant for a filename, and I was to call my own function to open up that file, it shouldn't matter if it's static even if that function was in another file (unless I was passing the address of it)... or am I mixing this up. I've never really used static much, to be honest.

– RastaJedi
3 hours ago













@RastaJedi: At file scope (outside of any function), static essentially just changes whether the thing may be known outside the current translation unit. Inside a block (any set of statements in braces in a function, main or other), static both says “this name is not known outside this block” and “this thing sticks around for all of program execution, not just block execution.” With a const object, though, the two lifetimes (static and automatic) often optimize to the same thing. (Taking addresses of things can change that, for semantic reasons, but simple uses are unaffected.)

– Eric Postpischil
3 hours ago





@RastaJedi: At file scope (outside of any function), static essentially just changes whether the thing may be known outside the current translation unit. Inside a block (any set of statements in braces in a function, main or other), static both says “this name is not known outside this block” and “this thing sticks around for all of program execution, not just block execution.” With a const object, though, the two lifetimes (static and automatic) often optimize to the same thing. (Taking addresses of things can change that, for semantic reasons, but simple uses are unaffected.)

– Eric Postpischil
3 hours ago













So if I have a static string constant, and pass it to a routine in another TLU, this would still work, but the possibility of optimization goes away, is what you are getting at? Within a function, try to mark it static if I don't need to change it anywhere else or pass it to any other routine, for a possibility of optimization? What about the cases of non-constant values. Just use static if I need it's value to stick around when it goes out of scope or to limit to that TLU within file scope? I'm assuming there's no possibility of it being optimized in this way if it is modifiable.

– RastaJedi
2 hours ago





So if I have a static string constant, and pass it to a routine in another TLU, this would still work, but the possibility of optimization goes away, is what you are getting at? Within a function, try to mark it static if I don't need to change it anywhere else or pass it to any other routine, for a possibility of optimization? What about the cases of non-constant values. Just use static if I need it's value to stick around when it goes out of scope or to limit to that TLU within file scope? I'm assuming there's no possibility of it being optimized in this way if it is modifiable.

– RastaJedi
2 hours ago













Given static const char * const ptr = "string"; at function level, passing ptr to a routine outside the current translation unit should have the same effect as passing "string" or array, where array is const char array[] = "string";. In all those cases, the compiler only needs to pass the address of the actual string, which itself may not be changed. So it should produce the same code for all of them. If you passed &ptr outside the module, then the compiler has to create an actual ptr so it can take its address. But that is a different use case.

– Eric Postpischil
2 hours ago





Given static const char * const ptr = "string"; at function level, passing ptr to a routine outside the current translation unit should have the same effect as passing "string" or array, where array is const char array[] = "string";. In all those cases, the compiler only needs to pass the address of the actual string, which itself may not be changed. So it should produce the same code for all of them. If you passed &ptr outside the module, then the compiler has to create an actual ptr so it can take its address. But that is a different use case.

– Eric Postpischil
2 hours ago













Outside a function, mark anything static if it does not need to be known outside the current translation unit. Inside a function (or block), identifiers are already not known outside the function (or block), as if they were static. There, using static actually adds a property that they persist for program execution instead of function/block execution, so do not use static inside a function/block unless you need that property.

– Eric Postpischil
2 hours ago





Outside a function, mark anything static if it does not need to be known outside the current translation unit. Inside a function (or block), identifiers are already not known outside the function (or block), as if they were static. There, using static actually adds a property that they persist for program execution instead of function/block execution, so do not use static inside a function/block unless you need that property.

– Eric Postpischil
2 hours ago











1














From the performance perspective, this is a fairly small optimization which makes sense for low-level code that needs to run with the lowest possible latency.



However, I would argue that const char s3[] = "bux"; is better from the semantic perspective, because the type of the right hand side is closer to type of the left hand side. For that reason, I think it makes sense to declare string constants with the array syntax.






share|improve this answer





















  • 1





    Aren't string literals in C not technically const-qualified type? Despite being immutable. Or you just meant the array aspect of it perhaps. Also doesn't the array version have to copy an entire string?

    – RastaJedi
    3 hours ago













  • You are correct. However, it's UB to modify the elements of a string literal, and I was referring to the array part. :)

    – merlin2011
    3 hours ago
















1














From the performance perspective, this is a fairly small optimization which makes sense for low-level code that needs to run with the lowest possible latency.



However, I would argue that const char s3[] = "bux"; is better from the semantic perspective, because the type of the right hand side is closer to type of the left hand side. For that reason, I think it makes sense to declare string constants with the array syntax.






share|improve this answer





















  • 1





    Aren't string literals in C not technically const-qualified type? Despite being immutable. Or you just meant the array aspect of it perhaps. Also doesn't the array version have to copy an entire string?

    – RastaJedi
    3 hours ago













  • You are correct. However, it's UB to modify the elements of a string literal, and I was referring to the array part. :)

    – merlin2011
    3 hours ago














1












1








1







From the performance perspective, this is a fairly small optimization which makes sense for low-level code that needs to run with the lowest possible latency.



However, I would argue that const char s3[] = "bux"; is better from the semantic perspective, because the type of the right hand side is closer to type of the left hand side. For that reason, I think it makes sense to declare string constants with the array syntax.






share|improve this answer















From the performance perspective, this is a fairly small optimization which makes sense for low-level code that needs to run with the lowest possible latency.



However, I would argue that const char s3[] = "bux"; is better from the semantic perspective, because the type of the right hand side is closer to type of the left hand side. For that reason, I think it makes sense to declare string constants with the array syntax.







share|improve this answer














share|improve this answer



share|improve this answer








edited 3 hours ago

























answered 3 hours ago









merlin2011merlin2011

44k26119218




44k26119218








  • 1





    Aren't string literals in C not technically const-qualified type? Despite being immutable. Or you just meant the array aspect of it perhaps. Also doesn't the array version have to copy an entire string?

    – RastaJedi
    3 hours ago













  • You are correct. However, it's UB to modify the elements of a string literal, and I was referring to the array part. :)

    – merlin2011
    3 hours ago














  • 1





    Aren't string literals in C not technically const-qualified type? Despite being immutable. Or you just meant the array aspect of it perhaps. Also doesn't the array version have to copy an entire string?

    – RastaJedi
    3 hours ago













  • You are correct. However, it's UB to modify the elements of a string literal, and I was referring to the array part. :)

    – merlin2011
    3 hours ago








1




1





Aren't string literals in C not technically const-qualified type? Despite being immutable. Or you just meant the array aspect of it perhaps. Also doesn't the array version have to copy an entire string?

– RastaJedi
3 hours ago







Aren't string literals in C not technically const-qualified type? Despite being immutable. Or you just meant the array aspect of it perhaps. Also doesn't the array version have to copy an entire string?

– RastaJedi
3 hours ago















You are correct. However, it's UB to modify the elements of a string literal, and I was referring to the array part. :)

– merlin2011
3 hours ago





You are correct. However, it's UB to modify the elements of a string literal, and I was referring to the array part. :)

– merlin2011
3 hours ago


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54975623%2fhow-should-i-define-declare-string-constants%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Paper upload error, “Upload failed: The top margin is 0.715 in on page 3, which is below the required...

Emraan Hashmi Filmografia | Linki zewnętrzne | Menu nawigacyjneGulshan GroverGulshan...

How can I write this formula?newline and italics added with leqWhy does widehat behave differently if I...