Passing right argument to function with `char const* str` - c

Setup
#define functionA(str) functionB(PSTR(str))
void functionB(char const* str) { ... something, e.g. print str... }
void functionC(char const* str) {
functionA("Hello World"); // this one work
functionA(str); // however this doesn't work
}
Problem
I have a function function B which I try to use. If I simply call it with "some string" it works perfectly. However if I try to call it in functionC with the argument str, the compiler returns the error "invalid initializer" and the message "in expansion of macro PSTR". How can I fix this, where is my problem?
EDIT - additional information
The program runs on an AT Mega and the PSTR is also from AT-Mega
#define PSTR(s) ((const PROGMEM char *)(s))
#else /* !DOXYGEN */
/* The real thing. */
# define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];}))
#endif /* DOXYGEN */
#define PROGMEM __ATTR_PROGMEM__
#ifndef __ATTR_PROGMEM__
#define __ATTR_PROGMEM__ __attribute__((__progmem__))
#endif

You cannot mix program space and regular strings, since they are stored in different memory spaces. The AVR architecture separates data and program memory, and regular variables/strings live in the data memory (RAM). But since RAM is often very limited on these devices, constant data (such as strings) may be stored in program space to avoid using RAM. The PSTR macro is provided to do this for string literals.
The reason for your error with functionA(str) is simply that it ends up using the macro as PSTR(str), and PSTR only works with string literals since you cannot place data in program space at runtime. But also note that while PSTR("Hello world") works, your functionB must specifically expect a program space string or it will treat the pointer as though it pointed to RAM (which it doesn't).
To use a program space string, you may either take a PSTR as an argument and handle it with the pgm_* functions/macros (such as pgm_read_byte), or first copy the PSTR to RAM (such as with strcpy_P) and then pass that to a function expecting a regular string. See avr/pgmspace.h.

Related

C test if variable is in read-only section

I'd like to write a low-level logging function that would look like:
DO_DBG("some string", val1, val2)
What I want it to do, is to store the pointer to the string rather than a copy of the string, for performance reasons. This assumes that the string is a read-only literal. To prevent people having to debug the debugger, it would be nice if the compiler could complain if the first parameter of DO_DBG was in a writable section of code vs text, etc. I'm wondering if a mechanism to do that exists. (I'm using gcc 4.9.1, ld 2.24).
You could use the automatic literal string concatenation to your advantage:
#define DO_DBG(s, a, b) _DO_DBG("" s, a, b)
And implement your real macro as _DO_DBG.
You can set up a SIGSEGV handler, and then try to do:
s[0] = s[0];
If the handler is triggered, it means that the variable is in a read-only segment, so you can save the pointer. If not, you can complain (or just make a copy of the string).
You'll need to declare the string volatile so the compiler doesn't optimize the assignment away.
Alternatively you could use the stringify macro construct:
#define DO_DBG(s, a, b) DO_DBG_INTERNAL(# s, a, b)
and call your function DO_DGB_INTERNAL
so people would do:
DO_DBG(some string, val1, val2)
PS, quite possibly a variadic function and macro would be a good idea here.
Your function gets a pointer to the start of the string. If your operating system allows it, and the compiler sets it up that way, a constant string (like in your example) could be allocated in a read-only memory area. If your compiler is smart, it will store one copy of a string constant that appears several times. It might even figure out that some strings are never used, and just not store them at all.
Other than the above, unless your program relies on undefined behaviour (getting away with writing on a constant string), you should not be able to figure out if it is in read-only memory or not. You could compare addresses of strings to see if they are only one copy, but that is it.
In any reasonable C implementation (i.e., one that doesn't go out of its's way just to screw you over), you will see no (or at most an extremely small) performance difference if the string is read-only, read-write, one copy or several.
If you write you function with a char * parameter, and store said pointer away (not a copy to the string pointed to), you should always get the same string back (unless your environment is really strange).
Here's a SIGSEGV-handler-based test to check if pointed-at memory is mapped read-only:
#define _GNU_SOURCE
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <setjmp.h>
static sigjmp_buf label;
static void segv_hndlr(int Sig) { siglongjmp(label,1); } //safe in this ctx
_Bool is_ro(char volatile *X)
{
_Bool r=0;
struct sigaction old;
X[0]; //fault now if the target isn't writable
if(sigsetjmp(label,1))
{ r=1; goto out; }
sigaction(SIGSEGV,&(struct sigaction){.sa_handler=segv_hndlr}, &old);
X[0]=X[0];
out: sigaction(SIGSEGV,&old, NULL);
return r;
}
//example:
int main()
{
#define PR_BOOL(X) printf(#X"=%d\n", X)
char bar[]="bar";
char *baz = strdup("baz");
static int const static_ro_int = 42;
int const auto_ro_int = 42;
PR_BOOL(is_ro("foo")); //1
PR_BOOL(is_ro(bar)); //0
PR_BOOL(is_ro(baz)); //0
PR_BOOL(is_ro((void*)&static_ro_int)); //1
PR_BOOL(is_ro((void*)&auto_ro_int)); //0
}

How to pass a string literal to a function with explicit section storage

Please forgive if this has been asked before, but I couldn't find a question like it.
The problem is like this: for a certain microcontroller I need selected string literals to be in another section than the default .rodata section. The "other" section will be put in flash (which can only be read 4 bytes at a time, so it can't be used freely, the function needs to be aware of the fact), while the .rodata section gets copied into ram, which is useful, because ram can be read without alignment restrictions, but it is very limited in size.
The construction I now use is like this:
#define roflash __attribute__((section(".flash.rodata"))) __attribute__((aligned(sizeof(char*))))
static roflash const char literal[] = "text";
(+ modifications in the loader script of course).
This works as intended. But it means for every string handling function I'm calling something like this:
static roflash const char literal[] = "text";
do_something(literal);
The holy grail would be something that can combine both into one "black box" construction, so I can write do_something_roflash("text");
I guess it would be something with a #define and a code block, so the same variable name could be used over and over again. But then I get stuck, because some of the functions have a variable number of arguments, so something like this won't work:
#define function_roflash(s) { \
static roflash const char str[] = s; \
function_roflash_implementation(s); \
}
In fact I guess I'd need a variable-argument #define, does that exist?
Other solutions also very welcome.
Thx.
One idea for a somewhat generic GCC variadic macro is:
#define roflash(func, str, ...) { \
static roflash const char s[] = str; \
func(s, __VA_ARGS__); \
}
With just one macro you could support many functions that accept one string constant as the first parameter:
roflash(printf, "%d", 42);
roflash(do_something, "text");
roflash(obj.write, "text");
roflash(obj->write, "text");

Perform special kind of initialization of string in C

As you know in C, we can initialize string variables like this:
char text[1024] =
"Hello "
"World";
But what if I have a function that returns the word "World"?
char text[1024] =
"Hello "
World();
It seems to me that's not possible in C.
Please confirm.
What you want is not possible.
The L-value to the assigment operator needs to be modifyable, which an array isn't.
From the C11-Standard:
6.5.16/2
An assignment operator shall have a modifiable lvalue as its left operand.
The only exception to this is during initialisation when using literals as R-value:
char text[1024] = "Hello ""World";
From the C11-Standard:
6.7.9/14
An array of character type may be initialized by a character string literal or UTF−8 string
literal, optionally enclosed in braces. Successive bytes of the string literal (including the
terminating null character if there is room or if the array is of unknown size) initialize the
elements of the array.
If World() is something that always returns "World", then define it as a macro:
#define World "World"
And then do:
char text[1024] =
"Hello "
World; //Without parentheses
EDIT
String concatenation in the way you expect to do is made by the C preprocessor.You are actually looking for a runtime concatenation of two strings, which can be performed in multiple ways. The simplest one is achieved by strcat function, but the initialization should be performed explicitly by a function:
char text[1024];
void init_text() {
strcpy(text, "Hello ");
strcat(text, World()); //World() defined somewhere else
}
Alternative using sprintf :
void init_text() {
sprintf(text, "Hello %s", World());
}
Then in the main function, call init_text() at the beginning:
int main() {
init_text();
...
}
It is not possible in standard C to initialize something with some runtime specific behavior. So the standard portable way is to initialize the data by calling a function at the beginning of main, as answered by Claudix.
However, if you are using some recent GCC compiler (or Clang/LLVM) you could otherwise, on some systems (including Linux and probably other POSIX systems), use some constructor attribute on function. So you would declare:
static void init_text(void) __attribute__((constructor));
and define init_text like in Claudix's answer without having to call it in your main : since it has the constructor attribute, it would be called magically before main, or during dlopen(3) if it appears inside a dynamically linked plugin or library.
A more portable trick might be to have a function returning that text which will initialize it during its first call. So instead of using text you would call get_my_text() everywhere (perhaps by putting #define text get_my_text() in a header, but I don't recommend doing so for readability reasons, so replace every occurrence of text by get_my_text() ...), and define it as:
const char*get_my_text() {
static char textbuf[1024];
if (textbuf[0]) {
// already initialized, so return it
return textbuf;
};
snprintf(textbuf, sizeof(textbuf), "Hello %s", World());
return textbuf;
}
Beware that such a trick is not reliable in multi-threaded programs: two threads might run get_my_text exactly at the same time, and you have a data race. In a multi-threaded app use e.g. pthread_once
You could even define get_my_text as a static inline function in your header file.
PS Always prefer snprintf(3) to sprintf to avoid buffer overflows. Also notice that in standard C++ any static or global data with some given constructor is initialized before main ... hence the name of GCC function attribute...

Know if const qualifier is used

Is there any way in C to find if a variable has the const qualifier? Or if it's stored in the .rodata section?
For example, if I have this function:
void foo(char* myString) {...}
different actions should be taken in these two different function calls:
char str[] = "abc";
foo(str);
foo("def");
In the first case I can modify the string, in the second one no.
Not in standard C, i.e. not portably.
myString is just a char* in foo, all other information is lost. Whatever you feed into the function is automatically converted to char*.
And C does not know about ".rodata".
Depending on your platform you could check the address in myString (if you know your address ranges).
You can't differ them using the language alone. In other words, this is not possible without recurring to features specific to the compiler you're using, which is likely not to be portable. A few important remarks though:
In the first case you COULD modify the string, but you MUST NOT. If you want a mutable string, use initialization instead of assignment.
char *str1 = "abc"; // NOT OK, should be const char *
const char *str2 = "abc"; // OK, but not mutable
char str3[] = "abc"; // OK, using initialization, you can change its contents
#include<stdio.h>
void foo(char *mystr)
{
int a;
/*code goes here*/
#ifdef CHECK
int local_var;
printf(" strings address %p\n",mystr);
printf("local variables address %p \n",&local_var);
puts("");
puts("");
#endif
return;
}
int main()
{
char a[]="hello";
char *b="hello";
foo(a);
foo(b);
foo("hello");
}
On compiling with gcc -DCHECK prog_name.c and executing on my linux machine the following output comes...
strings address 0xbfdcacf6
local variables address 0xbfdcacc8
strings address 0x8048583
local variables address 0xbfdcacc8
strings address 0x8048583
local variables address 0xbfdcacc8
for first case when string is defined and initialized in the "proper c way for mutable strings" the difference between the addresses is 0x2E.(5 bytes).
in the second case when string is defined as char *p="hello" the differences in addresses is
0xB7D82745.Thats bigger than the size of my stack.so i am pretty sure the string is not on the stack.Hence the only place where you can find it is .rodata section.
The third one is similar case
PS:As mentioned above this isn't portable but the original question hardly leaves any scope for portability by mentioning .rodata :)
GCC provides the __builtin_constant_p builtin function, which enables you to determine whether an expression is constant or not at compile-time:
Built-in Function: int __builtin_constant_p (exp)
You can use the built-in function __builtin_constant_p to determine if a value is known to be constant at compile-time and hence that GCC can perform constant-folding on expressions involving that value. The argument of the function is the value to test. The function returns the integer 1 if the argument is known to be a compile-time constant and 0 if it is not known to be a compile-time constant. A return of 0 does not indicate that the value is not a constant, but merely that GCC cannot prove it is a constant with the specified value of the `-O' option.
So I guess you should rewrite your foo function as a macro in such a case:
#define foo(x) \
(__builtin_constant_p(x) ? foo_on_const(x) : foo_on_var(x))
foo("abc") would expand to foo_on_const("abc") and foo(str) would expand to foo_on_var(str).

How do you declare string constants in C?

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

Resources