Given the following function in c:
int reset_values_of_string(char* s, int to_new_val){
int l = strlen(s);
int was_changed = 0;
for(int i=0; i<l; i++) {
if(s[i] != to_new_val) was_changed=1;
s[i] = to_new_val;
}
return was_changed;
}
Can I write this function as MACRO (#define) in C? that will do exactly the same and will return this value ?
In addition, what is bascially preferred? to implement it with macro or with function like that i write it above.
Can I write this function as MACRO (#define) in C? That will do exactly the same and will return this value
Yes, and it will be close enough to the function.
What is basically preferred?
A function would be preferred.
Modern compilers can choose to automatically inline functions if they deem it a better option. You may also encourage compilers to inline functions.
Related
I want to generate an array initializer with arbitrary logic that unfortunately requires some looping.
#define RANDOM_ARRAY(n) \
...
double array[] = RANDOM_ARRAY(10);
Suppose the code above generates an initializer for a 10-element array. Is it possible to define such a macro (with a loop) in C99 ?
NB: it doesn't have to be a macro if a function call could suffice (but it has to be possible to call it among global initializers, not in a second function);
Unfortunately, it is not possible to create a recursive (or loop) macrofunction in C. Nevertheless, if you have a reasonable maximum length for your initializer, you can use this type of construct :
#define INITIALIZER(N) { INITIALIZER_ ## N }
#define INITIALIZER_1 1
#define INITIALIZER_2 INITIALIZER_1, 2
#define INITIALIZER_3 INITIALIZER_2, 3
int
main(void)
{
int tab[3] = INITIALIZER(3);
return 0;
}
The C preprocessor doesn't support loops, so what you want is not (easily) possible.
I added the '(easily)' because there are ways to get loop-like behavior using something like boost's ITERATE. This uses recursive file inclusion to emulate a loop. But I'm not sure if you want to go that far.
Since you're working in C99, you can of course create a macro that does the initialization, but you won't be able to make it look like an initializer:
#define INCREMENTING_ARRAY(t,a,n) t a[n]; do {\
for(size_t i = 0; i < n; ++i)\
a[i] = i;\
} while(0);
This creates an array whose elements are initialized to be incrementing, as an example.
Usage:
int main(void)
{
INCREMENTING_ARRAY(int, dozen, 12);
int i;
for(i = 0; i < sizeof dozen / sizeof *dozen; ++i)
printf("array at %d = %d\n", i, dozen[i]);
return 0;
}
This works since in C99 you can freely mix declarations and code, so the int i; after the macro usage is fine. In C89, it wouldn't have worked.
I want to replace array subscript of a C code with a call to a hash function. Is it possible to do this using a C macro?
This is an old code and it is very difficult to make changes to it. It will be very helpful, if I could just use a macro and a hash function instead of changing the actual code.
int array[1000];
// I want to define a macro such that array[idx] will be replaced with
// array[hash(idx)] and then define a function called hash(idx) which
// will return an integer within the bounds of the array (0..999)
int main()
{
int input;
scanf("%d", &input);
array[input] = 1;
return 0;
}
I'm new to C and C++, and I've read that at least in C++ it's preferable to use std::array or std::vector when using vectors and arrays, specially when passing these into a function.
In my research I found the following, which makes sense. I suppose using std::vector would fix the problem of indexing outside of the variable's scope.
void foo(int arr[10]) { arr[9] = 0; }
void bar() {
int data[] = {1, 2};
foo(data);
}
The above code is wrong but the compiler thinks everything is fine and
issues no warning about the buffer overrun.
Instead use std::array or std::vector, which have consistent value
semantics and lack any 'special' behavior that produces errors like
the above.
(answer from bames53, thanks btw!)
What I want to code is
float foo(int X, int Y, int l){
// X and Y are arrays of length l
float z[l];
for (int i = 0; i < l; i ++){
z[i] = X[i]+Y[i];
}
return z;
}
int bar(){
int l = 100;
int X[l];
int Y[l];
float z[l];
z = foo(X,Y,l);
return 0;
}
I want this to be coded in C, so my question is is there a std::vector construct for C? I couldn't find anything on that.
Thanks in advance, also please excuse my coding (I'm green as grass in C and C++)
Standard C has nothing like std::vector or other container structures. All you get is built-in arrays and malloc.
I suppose using std::vector would fix the problem of indexing outside of the variable's scope.
You might think so, but you'd be wrong: Indexing outside of the bounds of a std::vector is just as bad as with a built-in array. The operator[] of std::vector doesn't do any bounds checking either (or at least it is not guaranteed to). If you want your index operations checked, you need to use arr.at(i) instead of arr[i].
Also note that code like
float z[l];
...
return z;
is wrong because there are no array values in C (or C++, for that matter). When you try to get the value of an array, you actually get a pointer to its first element. But that first element (and all other elements, and the whole array) is destroyed when the function returns, so this is a classic use-after-free bug: The caller gets a dangling pointer to an object that doesn't exist anymore.
The customary C solution is to have the caller deal with memory allocation and pass an output parameter that the function just writes to:
void foo(float *z, const int *X, const int *Y, int l){
// X and Y are arrays of length l
for (int i = 0; i < l; i ++){
z[i] = X[i]+Y[i];
}
}
That said, there are some libraries that provide dynamic data structures for C, but they necessarily look and feel very different from C++ and std::vector (e.g. I know about GLib).
Your question might be sensitive for some programmers of the language.
Using constructs of one language into another can be considered cursing as different languages have different design decisions.
C++ and C share a huge part, in a way that C code can (without a lot of modifications) be compiled as C++. However, if you learn to master C++, you will realize that a lot of strange things happen because how C works.
Back to the point: C++ contains a standard library with containers as std::vector. These containers make use of several C++ constructions that ain't available in C:
RAII (the fact that a Destructor gets executed when the instance goes out-of-scope) will prevent a memory leak of the allocated memory
Templates will allow type safety to not mix doubles, floats, classes ...
Operator overloading will allow different signatures for the same function (like erase)
Member functions
None of these exist in C, so in order to have a similar structure, several adaptions are required for getting a data structure that behaves almost the same.
In my experience, most C projects have their own generic version of data structures, often based on void*. Often this will look similar like:
struct Vector
{
void *data;
long size;
long capacity;
};
Vector *CreateVector()
{
Vector *v = (Vector *)(malloc(sizeof(Vector)));
memset(v, 0, sizeof(Vector));
return v;
}
void DestroyVector(Vector *v)
{
if (v->data)
{
for (long i = 0; i < v->size; ++i)
free(data[i]);
free(v->data);
}
free(v);
}
// ...
Alternatively, you could mix C and C++.
struct Vector
{
void *cppVector;
};
#ifdef __cplusplus
extern "C" {
#endif
Vector CreateVector()
void DestroyVector(Vector v)
#ifdef __cplusplus
}
#endif
vectorimplementation.cpp
#include "vector.h"
struct CDataFree
{
void operator(void *ptr) { if (ptr) free(ptr); }
};
using CData = std::unique_ptr<void*, CDataFree>;
Vector CreateVector()
{
Vector v;
v.cppVector = static_cast<void*>(std::make_unique<std::vector<CData>>().release());
return v;
}
void DestroyVector(Vector v)
{
auto cppV = static_cast<std::vector<CData>>(v.cppVector);
auto freeAsUniquePtr = std::unique_ptr<std::vector<CData>>(cppV);
}
// ...
The closest equivalent of std::array in c is probably a preprocessor macro defintion like
#define ARRAY(type,name,length) \
type name[(length)]
I heard from a programmer (actually an IT teacher) that I should never write this:
void foo(bool foobar) {
if(foobar) {
size_t i;
for (i = 0; i < 42; i++) {
// Do something
}
}
}
But this:
void foo(bool foobar) {
size_t i;
if(foobar) {
for (i = 0; i < 42; i++) {
// Do something
}
}
}
Why?
Moreover, it seems that size_t is also bad because using a unsigned value prevent the compiler to do a good optimization.
That's nonsense. Always reduce the scope of variables as much as possible.
As for performance, it doesn't matter in the slightest. Since a local variable has automatic storage, the compiler will stack your variable just before it is used, no matter where the declaration appears in the source code.
That size_t would prevent the compiler from effectively optimizing your code is also nonsense.
Now what you should do, for scope and style reasons:
for (size_t i = 0; i < 42; i++)
And if this doesn't compile, you need to upgrade to a compiler which isn't older than 15 years.
It is only about subjective matter of coding style. The both codes compiles equally to the same behaviour. One may preffer:
void foo(bool foobar) {
size_t i;
if (foobar) {
for (i = 0; i < 42; i++) {
// Do something
}
}
}
as variable declaration is listed at the top. The second school is to declare variable closest to its usage (this code is perfectly valid in C89), so:
void foo(bool foobar) {
if (foobar) {
size_t i;
for (i = 0; i < 42; i++) {
// Do something
}
}
}
can be preferred instead. Using a C99/C11 compiler it would be even to better to declare it directly in the for loop:
void foo(bool foobar) {
if (foobar) {
for (size_t i = 0; i < 42; i++) {
// Do something
}
}
}
Old-style C (K&R) required all auto variables (in the old sense) to be declared at the beginning of the function after the part that set out the parameter types.
Newer standards (ANSI C) relax that, and modern coding conventions prefer keeping the scope of variables as tight as possible as that increases program stability.
I'd go one stage further and write (possible since C99)
for (size_t i = 0; i < 42; i++)
as then the scope of i is limited to the for loop: there's no danger it will be relied upon in error in other parts of your program.
As for using size_t as the counter, I can't see why that would constrain a compiler's optimisation strategy. In fact, I'd suspect that < could be faster on unsigned types since you don't need to handle a sign bit.
I'm reading over a solution to a problem in K&R's chapter 7 posted here. Basically, the program will convert the standard input into lowercase or uppercase depending on the name of the program ("upper" or "lower"). It seems to store the names of the conversion functions in some kind of dictionary, like so:
int (*convcase[2])(int) = {toupper, tolower};
and later access these functions depending on whether the name of the program started with a u or an l:
if(argc > 0)
{
if(toupper((unsigned char)argv[0][0]) == 'U')
{
func = 0;
}
else
{
func = 1;
}
while((ch = getchar()) != EOF)
{
ch = (*convcase[func])((unsigned char)ch);
putchar(ch);
}
}
I understand what that code block is doing, but I've never seen anything like the initial declaration of convcase. It seems like some kind of weird combination of a macro, an enum, and an array. Could anyone explain (1) why convcase is a pointer; (2) what's with the (int) cast after its name; (3) what exactly toupper and tolower are within that declaration, because they're not char *s; and (4) when/why to use this kind of setup. Is it just a quick macro-like tool to save some space when you have multiple possible function calls?
convcase is an array of two function pointers; It's not a pointer. An array expression will be implicitly converted to a pointer when it is used in a place where a pointer is expected.
That's not a cast. It's specifying that the functions accept an int argument, as the toupper and tolower functions do.
convcase is initialised with the function pointers toupper and tolower.
I presume this question is regarding function pointers. Use function pointers when you wish for the abstraction of function pointers. I'd suggest that this example is an unnecessary use of function pointers. The ability to change convcase[0] or convcase[1] to Spanish or Japanese, depending upon user input would more likely warrant the use of function pointers in this case. Additionally, function pointers could be used in arguments to provide additional abstraction. For example, the qsort function is able to sort arrays of any type because of it's usage of function pointers for a comparer of objects. Here's an example that sorts int input using the int_compare function as the comparer.
#define nelem(array) (sizeof (array) / sizeof *(array))
int int_compare(const void *p1, const void *p2) {
int x = *(int *)p1, y = *(int *)p2;
return (x > y) - (y > x);
}
int main(void) {
int value[16];
for (size_t x = 0; x < nelem(value); x++) {
if (scanf("%d", &value[x]) != 1) {
break;
}
}
qsort(value, sizeof *value, x, int_compare);
return 0;
}