"statemenet with no effect" error in eclipse - c

I have this line of code,
newCust.idNumber == ID;
the value of ID is of type string and is already assigned, newCust is the name of my struct, and idNumber is a string in my struct, I want to assign the value of ID to the struct's ID Number, any idead why this line of code is a "statement with no effect" please. I am using eclipse, and I am a beginner in C programming

This is because == compares two values, and discards the result of that comparison. Although expression-statements like that are perfectly legal in C, they are highly unusual, and often serve as an indicator of you typing something incorrectly. That's why the compiler warns you about it.
EDIT:
I tried the = also, and i get this error then, incompatible types when assigning to type char[60] from type char *
You can't assign strings like that: you need to use strcpy, like this:
strcpy(newCust.idNumber, ID);
Make sure that newCust.idNumber is long enough to fit the ID together with its null terminator, i.e. given that newCust.idNumber is char[60], the value of the ID must be 59 characters or less.

Because you're doing a comparison and throwing away the result. You probably wanted
newCust.idNumber = ID;
Note the single equal sign.

== checks for equality, it is not an assignment operator.
And since you do not check for the return code of the check, Eclipse (rightly) yells at you.

Related

Regex: Returned type of C functions

I'm trying to write a regular expression that will give me only the returned type of any (see edit) C function in a C file, ignoring spaces and newlines, but I'm not having any luck with it.
Edit: The returned types I have to consider are only basic C data types
Example:
signed
long long
int function1 ( int j, int n)
should give me:
signed long long int
How can I write (or think of a solution for) this regular expression?
The hardest part of the problem is probably answering the question: "how can I tell that I have reached the start of a function definition". Given the various rules of C, it's not clear that there is a "sure fire" answer - so the best you can probably do is come up with a rule that catches "most" situations.
Function definitions will have
A return type with possible qualifier (one or more of void, signed, unsigned, short, long, char, int, float, double, *)
Followed by a word
Followed by an open parenthesis.
This means something like this should work: (demo: http://regex101.com/r/oJ3xS5 )
((?:(?:void|unsigned|signed|long|short|float|double|int|char|\*)(?:\s*))+)(\w+)\s*\(
Note - this does not "clean up the formatting" - so a return value definition that spans multiple lines will still do so. It does have the advantage (compared to other solutions) that it looks specifically for the basic types that are defined in the link in your question.
Also note - you need the g flag to capture all the instances; and I capture the function name itself in its own capturing group (\w+). If you don't want / need that, you can leave out the parentheses. But I thought that having both the return type and the function name might be useful.
Afterthought: if you first strip out multiple white spaces and returns, the above will still work but now there will be no extraneous white space in the return value. For instance you could run your code through
cat source.c | tr '\n' ' ' | sed 's/\s+/ /' > strippedSource.c
then process with the regex above.
Concatenate all words using the OR operator:
\b((void|unsigned|signed|char|short|int|long|float|double)\s*)+\b
The \b at start and end are to prevent partial function names popping up (void longjmp comes to mind).
This will not catch typedefs such as uchar_8, or complicated pointer-to-pointer constructions such as void (* int)(*) (I just made this up, it may not mean anything).

Saw a strange if statement in some legacy C code

What I saw in an if statement was like this.
if((var = someFunc()) == 0){
...
}
Will the statement
(var = someFunc())
always return the final value of var no matter what environment we are in?
That is just a one-line way of assigning to a variable and comparing the returned value at the same time.
You need the parentheses around the assignment because the comparison operators have higher precedence than the assignment operator, otherwise var would be assigned the value of someFunc() == 0.
This is simply wrong. var is assigned, and then its value is overwritten by a constant 0. The return value of the function is therefore lost, and the if always fails. Most compilers would probably issue a warning about that nowadays, both because of the assignment within an if and because of the impossible if that results. The right way to do what was probably intended is
if((var = someFunc()) == 0) {
(Mind you, this might also be malicious code trying to introduce a vulnerability under the guise of a common newbie mistake. There was a case recently where someone tried to smuggle a check into the Linux kernel where they assigned the UID to 0 (i.e., root) while pretending to check for being root. Didn't work, though.)
This is correct, I use it all the time
if ((f=fopen(s,"r"))==NULL)
return(fprintf(stderr,"fopen(%s,r) failed, errno=%d, %s\n",s,errno,strerror(errno)));
/* successfully opened file s, read from FILE *f as you like */
I also use it when I calloc() memory.
You're assigning the return value of someFunc (fopen or calloc in my cases) to a variable AND also testing that return value, it's a semantic shortcut assuming you'll never want to debug the assignment and the test separately.

Pass by reference in C: how is result variable initialized?

I am new to C, and I have to make a mini calculator program (this is homework, but I'm not looking for the answer, just a little more understanding). Basically, one function must look like this:
int add(double d, double dd, double *result);
It will return a 0 if there are no errors, and -1 if an error occurred (in the case of addition, there wouldn't be many errors - but division for example, divide by 0 would be an error).
A user has to input two numbers into the terminal, those numbers then get used as the parameter values in the add method. What I don't understand is what is result initially when the method is called? Is it just null? And why would I want to return 0 or -1 and not result instead? For example:
double result;
returnValue = add(2.0, 5.0, &result);
Obviously I'll get 7 as the result, but how will I print that out without returning the result? returnValue is 0, so I know there were no errors, so now I need to print result.
C doesn't have pass by reference. You can pass in a pointer, which is what you're doing here, but C only has pass by value.
Now to your actual questions:
What I don't understand is what is result initially when the method is called? Is it just null?
No, the value of result is undefined before the add function is called. You have no guarantees whatsoever if you try to use the value of result before assigning to it, either by assigning to it in the function where it's declared or by assigning to it in add with code like *result = d + dd.
For that matter, a double can never be null. Null is a possible pointer value, not a possible floating-point number.
And why would I want to return 0 or -1 and not result instead?
If you were to return result directly, you'd have to have some kind of distinguished "calculation failed" return value, which is kind of messy and leaves the caller to check the result before using it. This way forces the caller of add to notice that there is status code as the return value, and if the caller wants to ignore it then they can (although you shouldn't ignore status codes).
Obviously I'll get 7 as the result, but how will I print that out without returning the result?
Ed Heal is right to suggest printf. If you're using Linux or Mac OS X, though, I'd also recommend running man printf from the terminal - it's often more convenient than opening a web browser.
Thank you for your honesty. It is refreshing.
The line should read
returnValue = add(2.0, 5.0, &result);
And to print out the result look up printf - That will do the trick.
The code you have written does not assign a value to result when the variable is declared. Thus it contains some random number. It is obviously bad to use this number to do anything, as it will cause your program to have unpredictable results. This would be what is referred to as an uninitialized variable error.
Your code does not refer to the variable before it is assigned, so I am not saying you have a bug. I am simply answering the question of what result contains before it is assigned to. If you want it to have a particular value, you can declare it like this:
double result = 7;
and it would always have some predefined value. Again, there is no need to do this in your case, I'm just saying you could if you wanted an always defined value.

How to return string from a char function

I want the function getCategory() to return "invalid" , instead of printing the word "invalid" (i.e instead of using printf ) when input to the function is invalid (i.e.when either height or weight are lower then zero).
please help:
#include<stdio.h>
#include<conio.h>
char getCategory(float height,float weight)
{
char invalid = '\0';
float bmirange;
if(height<=0 || weight<=0)
return invalid;
else
{
height=height*0.01; //1 centimeter = 0.01 meters
bmirange=[weight/(height*height)];
if(bmirange< 15 )
return starvation;
}
}
int main()
{
char Category;
float height,weight;
printf("enter height");
scanf("%f",&height);
printf("enter weight");
scanf("%f",&weight);
Category=getCategory(height,weight);
if(Category == 0)
printf("invalid");
else
printf("%c", Category);
}
NOTE: the original question has been altered many, many times and the code has changed just as often, introducing new errors in each iteration. I leave this answer as it answered the original code, see history. Below this answer there's an update giving advice instead of code, as that seems more appropriate here.
Hmm, astander removed his answer. But perhaps this is what you should actually have:*
char getCategory(float height,float weight)
{
char invalid = '\0';
if(height<=0 || weight<=0)
return invalid;
return 'c'; /* do something for the valid cases */
}
* originally the question contained height || weight <= 0 and no value for variable invalid.
Notes on the code:
With proper indentation, your program flow becomes clearer. I corrected your if-statement, assuming this was your intend, actually. The last line should contain what you currently left out in your question. I added an initialization in the first line, because having a value is better then not having a value (which means: if you don't initialize, it can be anything, really).
In your calling code, you can do this:
Category = getCategory(height, weight);
if(Category == 0)
printf("invalid");
else
printf("%c", Category);
which actually prints the word "invalid" to the output, if that was your intend.
Update: based on new text in the question, it's clear that the asker wants something else, so here's a new answer. I leave the above, it's still valid with the original question.
You're now asking not to print the word "invalid" and not to use a special value for the invalid case. Instead, you ask to return "invalid", which I understand as returning the string with the value "invalid" (which, taken in itself, is still returning a special value).
You cannot do it
In short: you cannot do that. The current function has return type char. I don't know the purpose of your function, but I'm sure you've given it some thought and there's a reason for using a char. A char can only contain one character. And the word "invalid" is multiple characters. You have a few options, choose whichever suits you best:
Other ways
change the return type to be string instead of char, this requires redesign of all code involved;
settle with returning a special value. You don't show the body of your function, but if it would normally never return \0, you can use that value, as in my example above. Of course, you can choose any other char value;
raise an exception and use a try/catch in the body. But you use C, not C++. Here's a link that describes using C++-style exception handling for C, but this may be a bit out-of-bounds, learning C can better be taken on a small step at the time.
What's commonly best practice
In normal situations, it is common to choose either special-case values (typical in older or more basic languages like C or assembler) or exceptions (typical for more structured languages like C++, Java, Python). It's commonly considered bad practice to change a complete function for the purpose of special-cases (like invalid input).
Why
Instead, the caller of the function should deal with these special cases. The reason for this is a very important rule in programming: the function can never know beforehand what users of that function want to do when something bad happens (illegal input). One may choose to print "Illegal input" (for commandline users), another wants to quit the program (for in a library) and yet another wants to ignore and do nothing (for automatic processing). In short: what you are trying to achieve, you should try to achieve differently (see option 2 and 3 above, and my original solution).
Teachers and textbooks
Using this approach is by far the easiest and also best to understand for any (future) co-workers as it follows common computer practices. Of course, I haven't seen your assignment or textbook, so I can't tell in what direction they want a solution, and it won't be the first textbook or teacher to first show you the wrong path, let you tremble, and then show you the right path.
The getCategory method doesn't always return (because of the if statement). Also, not sure about the height in if statement. Add another return invalid at the end of the method.
char getCategory(float height,float weight)
{
char invalid;
if(height<=0 || weight<=0)
return invalid;
return 0
}
you need to (very carefully) pore over your textbook to ascertain the multitude of errors in the above code.
1, your test in getCategory will almost certainly not do what you want it to do.
2, you ARE returning invalid in some cases (but not all, see #1). However, there is no way to know that as invalid has no known value.
3. in other cases, getCategory returns no value at all
You're defining a variable named invalid. Its contents are undefined (it could be anything from -128 to 127). When you return this variable you're returning anything; do you want to assign something to the invalid variable before you return it? e.g.
char invalid;
invalid = 'i';
if ( ... ) {
return invalid;
} else {
return 0;
}
What does invalid should be mapped to? You should have a convention like this:
char invalid_category = '?';
or perhaps:
#define INVALID_CATEGORY '?'
This is better defined outside of the getCategory function so that the calling code can access it.
Also it isn't evident what your code returns when valid arguments are passed to it.
By the way, in your function getCategory, you have a variable that is not used nor declared - starvation. Where does that come from? I doubt that is a global variable.
Also, the variable bmirange does not make sense nor would it compile
bmirange=[weight/(height*height)];
as you can see that is a left hand side expression (LHS) but you have used an array subscript operators on the right hand side of expression (RHS). That is an illegal statement!
What was your intention there? Was that meant to be a pair of parenthesis?
Can you confirm this?
A lot of the answers are confusing because the OP did not make themselves clear on what is the error nor an explanation as to what is going on which is leading others to end up with code posted that does not satisfy the OP.
Hope this helps,
Best regards,
Tom.

Logical value of an assignment in C

while (curr_data[1] != (unsigned int)NULL &&
((curr_ptr = (void*)curr_data[1]) || 1))
Two part question.
What will (curr_ptr = (void*)curr_data[1]) evaluate to, logically. TRUE?
Also, I know its rather hack-ish, but is the while statement legal C? I would have to go through great contortions to put the assignment elsewhere in the code, so I'd be really nice if I could leave it there, but if it's so egregious that it makes everyone's eyeballs burst into flames, I'll change it.
(curr_ptr = (void*)curr_data[1]) will evaluate to TRUE unless it is a null pointer.
Assuming that curr_data is an array of pointers, and what you want to do is to run the loop while the second of these pointers is not null, while assigning its value to curr_ptr, I would do:
while ((curr_ptr = (void*)curr_data[1]) != NULL) { ... }
To answer your questions:
It will evaluate to true if curr_ptr isn't set to NULL (i.e. curr_data[1] isn't 0).
I believe it's legal, but there are bigger problems with this line of code.
Anyway, I'm assuming you didn't write this code, because you're debating about leaving it in vs. taking it out. So I want you to find out who wrote this line of code and introduce them to a heavy blunt object.
(unsigned int)NULL is ridiculous. Why would you do this? This will probably be the same as just writing 0 (not sure if that's guaranteed by the standard).
What kind of data is in curr_data[1] if it's being cast to a pointer (and pointers are being cast to it)? If it's supposed to be holding a pointer as an integral type, you should use the type intptr_t or uintptr_t provided in <stdint.h> for that purpose (if you're compiler doesn't support C99 ptrdiff_t may be an acceptable substitute).
The || 1 at the end seems to be redundant. If curr_ptr = (void*)curr_data[1] would have evaluated to false, we would have caught that in the first condition.
It may be a pain in the ass, but seriously reconsider rewriting this line. It looks like an entry in the IOCCC.
Assignments are expressions in C, so what you have works. Changing the ; to {} means the exact same thing and is much clearer, do that change at the very least. Assignments in conditions should be avoided when you have a clearer alternative (which is usually true), but if this is clearest in this place, then use it.
The result of an assignment is the assigned-to object. a = value will do the assignment and then evaluate to a. This is used to do things like a = b = 0.
To further clean up the code, there's no need for the void cast, and if this is chars, use '\0' (the null character) instead of NULL (which is supposed to be used with pointers only).
You wouldn't have to go through "great contortions", that is completely equivalent to
while (curr_data[1]) {
curr_ptr = (void *)curr_data[1];

Resources