Pointers to variables? - c

Is it possible to have pointers to data variables? I know I can have, say, pointers to strings e.g. char *str[n] and I can perform a 'for' loop over those pointers to retrieve the strings ... str[i] where i is the index counter.
If I have some data e.g.
char var1;
int var2;
char var3;
and I wanted to get data from stdin I might use 3 separate calls to scanf()- just an example - to populate these variables.
Can I have 'an array of pointers to data' e.g. void *data[] where data[0] = char var1, data[1] = int var2 and data[2] = char var3, so that I could then use a single call to scanf() in a 'for' loop to populate these variables? (I'm assuming the type would have to be void to cater for the different types in the array)

I don't really recommend this, but here's the implementation you describe:
char var1;
int var2;
char var3;
void *vars[3];
char *types[3];
vars[0]=&var1; types[0]="%c";
vars[1]=&var2; types[1]="%d";
vars[2]=&var3; types[2]="%c";
for (int i=0;i<3;i++)
{
scanf(types[i],vars[i]);
}
You need the array of types so that scanf knows what it should expect.
However, this procedure is extremely unsafe. By discarding any type-safety, you invite crashes from malformed input. Also, if you misconfigure types[] then you will almost certainly crash, or see unexpected results.
By the time you've set up the arrays, have you really saved any code?
There are plenty of answers here that will allow you to use either a type-safe C++ solution, or as others have recommended, calling scanf() explicitly.

You certainly could have such a void *data[] array. You wouldn't be able to read those in via scanf, though, as you need a different format specifier for the different data types.
If you wanted to do this, you could iterate over an array of
struct dataType
{
void *data;
char *format_specifier;
}
or somesuch. However, I doubt this would be a good idea - you probably want to also prompt for each value, so you'd add another char *prompt to that struct, and you'll probably need other things later as well.
I suspect the code you'd end up writing to do this would be much more effort than simply scanf-ing n times, even for quite large n.

The problem is that this void * array would be dealing with datatypes of different sizes. For this problem, you'd probably want to use a struct and maintain an array of those instead. Or you could just put your data in as a byte array, but then you'd have to know how to "chop it up" properly.

you could have an array of void*, so *array[0] = var1, etc.

To illustrate the problem..
int main(int argc, char* argv[])
{
char var1 = 'a';
int var2 = 42;
char var3 = 'b';
void* stuff[3] = {0};
stuff[0] = &var1;
stuff[1] = &var2;
stuff[2] = &var3;
// Can't really use the array of void*'s in a loop because the
// types aren't known...
assert( var1 == (char)(*(char*)stuff[0]));
assert( var2 == (int)(*(int*)stuff[1]));
assert( var3 == (char)(*(char*)stuff[2]));
return 0;
}

Not directly, no. If you're able to use C++ in this situation, the closest you could do would be to wrap each variable in an object (either something like a variant_t or some templated, polymorphic solution). For instance, I believe you can do something like this:
class BaseType
{
public:
virtual void DoScanf();
};
template<typename TYPE>
class SubType : public BaseType
{
public:
SubType(const TYPE& data) : m_data(data) {}
const TYPE& m_data;
virtual void DoScanf()
{
// Your code here
}
};
int num1;
char char1;
SubType<int> num1Wrapper(num1);
SubType<char> char1Wrapper(char1);
// You can then make a list/vector/array of BaseTypes and iterate over those.

Looks like you are trying to implement a template (C++) equivalent in C. :D exactly that is what i am trying to do, for one of my project. I think mine case is less confusing as I am using only one datatype (some project specific structure), mine array would not be intermixing the datatypes.
Hey, do one thing try using a union of various data-types you intent to use, i think reading this shall not be a problem. As when your read-function using that union reads it, will be able to read it, because of the inherit C-type safety. What i mean here is the follow the same concept which we usually use to check a endianess of a machine.
These are few idea, i am myself working on, shall be able to complete this is a day or two. And only then i can tell you, if this is exactly possible or not. Good luck, if you are Implementing this for some project. Do share your solution, may be here itself, I might also find some answer. :)
I am using the array of void pointers.

If you want an array of variables that can be "anything" and you are working in C, then I think you want something like a struct that contains a typeid and a union.
Like this, maybe: (Note, quick example, not compile tested, not a complete program)
struct anything_t {
union {
int i;
double d;
char short_str[7]; /* 7 because with this and typeid makes 8 */
char *str; /* must malloc or strdup to use this */
}; /* pretty sure anonymous union like this works, not compiled */
char type; /* char because it is small, last because of alignment */
};
char *anything_to_str(char *str, size_t len, const struct anything_t *any)
{
switch(any->type) {
case 1: snprintf(str, len, "%d", any->i); break;
case 2: snprintf(str, len, "%f", any->d); break;
case 3: snprintf(str, len, "%.7s", any->short_str); break; /* careful, not necessarily 0-terminated */
case 4: snprintf(str, len, "%s", any->str); break;
default: abort(); break;
}
return str;
}
And I forgot to add the scanf part I intended:
char *scanf_anything(struct anything_t *inputs, size_t count)
{
int input_i;
struct anything_t *i;
for(input_i=0; input_i<count; ++input_i) {
any = inputs + input_i;
switch(any->type) {
case 1: scanf(" %d ", any->i); break;
case 2: scanf(" %lf ", any->d); break;
case 3: scanf(" %.6s ", any->short_str); break;
case 4: scanf(" %a ", any->str); break; /* C99 or GNU but you'd be a fool not to use it */
default: abort(); break;
}
}
}

Formally all the solutions presented here which are using void* have the same problem. Passing a void* as a variadic argument (like scanf) which expects another type of pointer put you in the "undefined behavior" domains (for the same reason, you should cast NULL to the correct type when passed as variadic argument as well).
on most common platforms, I see no reason for a compiler to take advantage of that. So it will probably work until a compiler maker find out that there is a test in SPEC where it allows to get a 0.000001% improvement :-)
on some exotic platforms, taking advantage of that is the obvious thing to do (that rule has been put for them after all; they are mostly of historical interest only but I'd not bet anything about embedded platforms; I know, using scanf on embedded platforms can be considered as strange)

All solutions above are valid but no one has yet mentioned that you can do what you want with a single simple scanf call:
scanf(%c%d%c",var1,var2,var3);

Related

Cast a struct member in GDB Pretty Print?

I want to pretty print this struct struct MyStruct { char buffer[16]; }. Depending on buffer[15] I want to print buffer as a 10 byte string or treat it as a pointer. The 10 byte case is simple and works return self.val['buffer'].string(length = 10)
The second case I can't figure out. I want to do something like (*(char**)buffer[0]). I'm not sure how to do that. I was thinking parse_and_eval could be easy even if its not optimal but I couldn't figure out how to access buffer. I also need to cast the buffer to a 32bit int (len = *(int*)(bufer+4);) I couldn't figure that out either.
If I interpret your description correctly, I think your data is actually layed out like this:
struct MyStruct {
union {
char string[10];
struct {
char *p;
int size;
} ptr;
}
int flag;
}
So I think casting the buffer to a pointer of that type, and then choosing the format based on mystruct->flag would make life easier for you.
Even if my interpretation is not correct, try to find the correct version of that struct that captures the duality of the data.

It's possible to make typedef or define char pointer with malloc?

What I want to do is have string256 act like: char* s = (char*)malloc(256);
string256 s; /* this is what Iam trying to do */
char* s = (char*) malloc(256); /* this is how it looks in real life */
and use it
strncpy(s, "__test__", 9)
s[9] = 0x00;
P.s. typedef or define or function code length doesn't matter. only matters string256 s;
I won't forget to use free or error checking;
full code will look like this :
__Free_String_if_Flag_true __Zero_Memory __check_for_Errors __string_256 string256
and use it
string256 s;
You can make a typedef of a char array:
typedef char char256[256];
char256 s ;
s[255] = '\0' ;
The variable will stop existing when out of scope, but you can make it global if you want it persistent.
In short, no.
A typedef defines a name for a type. char* s = (char*) malloc(256); is a variable declaration, not a type.
You could probably achieve something similar with macros, but I would strongly advise against it (for a start, it would obscure the fact that a free would be necessary at some point.)
As for the part of your question asking about ...or define...:
In short - Yes you can: (partially taking exception with some of the other comments/answers)
However, I also agree with those answers that suggest it may not be in the best form to use #defines for such calls. (but you can do it)
Edited (removed ";" from macro)
#define string256(s) char *(s) = malloc(256)
//...
string256(s); //use parenethesis
/...
strcpy(s, "yes I can");
s now contains "yes I can" and is null terminated (strcpy() does that)
Do not forget to also create a macro for free(...);

How to change a variable whose name is the user input?

For example, I have this block:
int nFirst, nSecond;
char sInput[10];
printf("Which variable to change to 10?");
scanf("%s", &sInput);
// BAD - inflexible and unmaintainable
if(strcmp(sInput,"nFirst") ==0){
nFirst = 10;
}
else if (strcmp(sInput,"nSecond")==0) {
nSecond =10;
}
Is there a nice way to do this? like treat a string as if its a variable name?
No, there is no "nice" way of doing this in C. Variable names (typically) aren't preserved in the generated machine code, except to support debugging. C doesn't have a built-in mechanism for translating a string value into a reference to a variable of the same name.
You would have to map variable names to variables manually. You could build a lookup table, associating a string value with the address of the corresponding variable:
struct vn {
char *varname;
void *addr;
Typeinfo t;
};
where Typeinfo is some enumeration or other mechanism for encoding the type of the variable, giving you something to the effect of
int foo;
double bar;
char *blurga;
struct vn varsByName[] = { {"foo", &foo, IntType},
{"bar", &bar, DoubleType},
{"blurga", blurga, CharPtrType} };
I don't recommend doing this.
Another, platform-dependent approach is to put all your variables into a shared library and then have access to them by names. Have a look at dlsym/dlopen functions.
void* handle = dlopen("mysymbols.so", RTLD_LOCAL | RTLD_LAZY);
int* var = (int*) dlsym(handle, user_typed_name);
*var = 10; /* modify the variable */
You could implement something like a dictionary or a two-dimensional array which contains the "variable name" and the value. Then this comes down to setting an array element to a new value.
Other than that: C# and other object oriented languages would allow this through reflection, but as C itself isn't object oriented, you can not do that (C++ support for this seems to be very limited).
You can do it with a macro:
#define MAYBESET(name) if (strcmp(sInput, #name) ==0 ){ name = 10; }
#name is the real value of name changed to a string literal.
For a small number of variables then your algorithm should perform well. If there are many variables that could be changed, rather than just two, then another algorithm should be considered. Making this pretty and clear isn't exactly easy in C.
If you really wanted this to be faster you could either do a hash table or use a switch/case like:
int First, Second; // Note that I got rid of your leading n
char sInput[10];
printf("Which variable to change to 10?");
scanf("%s", &sInput);
// BAD - inflexible and unmaintainable
// referring to character array overflow potential, I assume
switch (sInput[0])
{
case 'F':
if (0 == strcmp("irst", sInput+1) )
{
First = 10;
} else
{
// error
}
break;
case 'S':
if (0 == strcmp("econd", sInput+1) )
{
Second = 10;
} else
{
// error
}
break;
default:
// error
break;
}
If you don't like the way that this looks then you could use macros (#define) to make it less big looking, but it would turn out the same. Another option that you could employ would be to write a small program that output the source code of this program which would handle all of the repetitive and tedious parts.
Another way to do this, if all of the variables are of the same type, would be to create an array of them and input their index in rather than a name, but then you have to add code to check against inputting an index out of range of the size of the array.

Sacrificing expression of intent for memory management

I'm pretty new at C programming, and this type of thing keeps popping up. As a simple example, suppose I have a struct http_header with some char pointers:
struct http_header {
char* name;
char* value;
};
I want to fill an http_header where value is the string representation of an int. I "feel" like, semantically, I should be able to write a function that takes in an empty header pointer, a name string, and an int and fills out the header appropriately.
void fill_header(struct http_header *h, char* name, int value)
{
h->name = name;
char *value_str = malloc(100);
sprintf(value_str, "%d", value);
h->value = value_str;
}
int main(int argc, const char * argv[])
{
struct http_header h;
char *name = "Header Name";
int val = 42;
fill_header(&h, name, val);
...
free(h.value);
}
Here, the calling code reads exactly as my intent, but in this case I'm creating the value string dynamically, which means I'd have to free it later. That doesn't smell right to me; it seems like the caller then knows too much about the implementation of fill_header. And in actual implementations it may not be so easy to know what to free: consider filling an array of http_headers where only one of them needed to have its value malloced.
To get around this, I'd have to create the string beforehand:
void fill_header2(struct http_header *h, char* name, char *value_str)
{
h->name = name;
h->value = value_str;
}
int main(int argc, const char * argv[])
{
struct http_header h;
char *name = "Header Name";
int value = 42;
char value_str[100];
sprintf(value_str, "%d", value);
fill_header2(&h, name, value_str);
}
As this pattern continues down the chain of structures with pointers to other structures, I end up doing so much work in top level functions the lower level ones seem hardly worth it. Furthermore, I've essentially sacrificed the "fill a header with an int" idea which I set out to write in the first place. I'm I missing something here? Is there some pattern or design choice that will make my life easier and keep my function calls expressing my intent?
P.S. Thanks to all at Stackoverfow for being the best professor I've ever had.
Well, I would go with the first approach (with a twist), and also provide a destroy function:
struct http_header *make_header(char *name, int value)
{
struct http_header *h = malloc(sizeof *h);
/* ... */
return h;
}
void destroy_header(struct http_header *h)
{
free(h->name);
free(h);
}
This way the caller doesn't have to know anything about http_header.
You might also get away with a version that leaves the main allocation (the struct itself) to the caller and does it's own internal allocation. Then you would have to provide a clear_header which only frees that fill allocated. But this clear_header leaves you with a partially-valid object.
I think your problem is simply that you are programming asymmetrically. You should once and for all decide who is responsible for the string inside your structure. Then you should have two functions, not only one, that should be called something like header_init and header_destroy.
For the init function I'd be a bit more careful. Check for a 0 argument of your pointer, and initialize your DS completely, something like *h = (http_header){ .name = name }. You never know if you or somebody will end up in adding another field to your structure. So by that at least all other fields are initialized with 0.
If you are new at C programming, you might perhaps want to use the Boehm's conservative garbage collector. Boehm's GC works very well in practice, and by using it systematically in your own code you could use GC_malloc instead of malloc and never bother about calling free or GC_free.
Hunting memory leaks in C (or even C++) code is often a headache. There are tools (like valgrind) which can help you, but you could decide to not bother by using Boehm's GC.
Garbage collection (and memory management) is a global property of a program, so if you use Boehm's GC you should decide that early.
The general solution to your problem is that of object ownership, as others have suggested. The simplest solution to your particular problem is, however, to use a char array for value, i.e., char value[12]. 2^32 has 10 decimal digits, +1 for the sign, +1 for the null-terminator.
You should ensure that 1) int is not larger than 32-bits at compile-time, 2) ensure that the value is within some acceptable range (HTTP codes have only 3 digits) before calling sprintf, 3) use snprintf.
So by using a static array you get rid of the ownership problem, AND you use less memory.

Declare a struct with zero values instead of random memory?

I have a struct like this:
typedef struct string {
unsigned long length;
unsigned *data;
} string;
Can I write something so that when I do this:
string s;
the length property is zero, instead of whatever happens to be in the memory? data works well, as it's preset to zero or a null pointer.
Example of what happens right now:
string s;
printf("length: %lu\n", s.length);
printf("pointer: %lu\n", (unsigned long) s.data);
Result:
length: 140737488347584
pointer: 0
I want to avoid having to call an initialisation function on each new string just to set length to zero.
More information
Now that I think about it, it may not be really necessary to do this in my particular case (though it would be nice) because most people would initially set the string through ctou (which imports UTF-8 from char pointer) and that function sets length to zero anyway.
You could use
string s = {0,NULL};
To combine the two previous answers (sort of) I'd define something like
#define STRING_INITIALIZER {0, NULL}
.
.
string s = STRING_INITIALIZER;
BTW, your struct declaration itself looks weird for a string. Either this is not a string as we usually understand it in C but merely a dynamic array of unsigned, or it is really a string and then this should be char*.
The accepted answer answered the question that you asked, but didn't address whether you ought.
Your string is a class and has class semantics. The initializer may be fine for kernel code where every last instruction counts, but in application code your static initializers are ugly and error prone.
It is possible to write classes in C, the stdio FILE type is a fabulous example, and here is the same idea applied to your string class:
typedef struct {
int length;
char *data;
} String;
String *sopen() {
String *s = malloc(sizeof(String));
if(s) {
s->length = 0;
s->data = NULL;
}
return s;
}
int sclose(String *s) {
free(s->data);
free(s);
return 0;
}
int main()
{
String *s = sopen();
return sclose(s);
}
Where I've followed the FILE* function name style for metaphoric reasons. Yep, there's more code. Yep, you have to explicitly deallocate the structure; but note that even though you were counting on auto class initialization in your code sample, if data was ever allocated, you couldn't count on leaving scope to automatically deallocate the storage for you.
This approach also has the merit of abstracting the type of data from the users of the class. As there seems to be some confusion about what type you really want to use, this flexibility may come in handy.
#define DEFINE_STRING(s) string s = {0, NULL}
{
DEFINE_STRING(s);
}
You can use a macro to "do this automatically"

Resources