passing argument 1 of 'strlen' makes pointer from integer without a cast - gcc

It is not clear why I get a warning of:
[Warning] passing argument 1 of 'strlen' makes pointer from integer without a cast [enabled by default]
expected 'const char *' but argument is of type 'char'
on two of the 3 statements containing strlen() below.
Even when I attempted to cast *str it still gave the same warning.
bfr is a character buffer. *str points to that char buffer after the call to
gets(). If I use strlen(*str) I get a warning. If I use strlen(bfr) I do not.
But *str should be the equivalent to bfr. Thus the confusion regarding the error.
Now in reality, strlen arg 1 is defined as strlen(const char *string). So I
would have expected strlen(bfr) to also produce an error since bfr[] is a
char string and not a const char either.
And where is the integer that is being made into a pointer?
I am using gcc under wXDev-C++.
void test(){
FILE *fileID = fopen("somefile.txt","r");
char *str, len;
char bfr[16];
str = fgets(bfr,16,fileID); // str will be set equal to &bfr[0]
len = strlen(*str); // This gives a warning
len = strlen((const char)*str); // This gives a warning
len = strlen(bfr); // This does not give a warning
}

Sometimes you just need to take a fresh look in the morning at a problem. I realized that strlen is looking for a pointer to a string and 'str' is defined as a pointer. So *str would be a pointer to a pointer. So the warning was correct. It should read len = strlen(s) not len = strlen(*s). And it is 'str' pointing to 'bfr' not *str;
Answered my own question.

Related

Is const keyword mandatory while declaring"constexpr char*" string?

The project that I have just started working on has many instances of following,
constexpr const char* str = "Some Character(s)";
I wanted to understand, is the "const" keyword in above statement not redundant, as constexpr is implicitly constant?
It is mandatory because it won't compile if you remove it. This code:
constexpr char *str = "Some Character(s)";
Produces the following error on x64 GCC 11.2 (link):
error: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
1 | constexpr char *str = "Some Character(s)";
| ^~~~~~~~~~~~~~~~~~~
The implied const is for the pointer itself so a redundant const would actually be this:
constexpr const char *const str = "Some Character(s)";
// ^~~~~
const and constexpr has diferent behaivours, as both has the same prefix, you may think that they are the same, but constexpr means that an atribute (or function, or whatever) will be done in compile time, and const means that that atribute won't be modified (it is an inmutable value, you can modify it, but thats undefined behaivour), but maybe can't be evaluated at compile time.
Also, in that particular case, you can't create an char *from an string literal since -std=c++17

string length: invalid static_cast

I was expecting this sample code to work:
std::string s;
int number=1;
s = std::to_string(number);
int size=static_cast<int>(s.length);
However it gives the error:
main.cpp:178:39: error: invalid static_cast from type ‘’ to type ‘int’
int size=static_cast(s.length);
Then, I also tried:
int size=atoi(s.length);
Which gives me the error:
cannot convert ‘std::basic_string<_CharT, _Traits, _Alloc>::length<char, std::char_traits<char>
... to type ‘const char*’
Then, I tried this option:
int size=atoi(s.c_str());
This one worked. Any hints why atoi(s.length) does not work, and instead atoi(s.c_str()) is required?
So, suppose that I have the input string as 999, the total of digits will be 3. Using s.length would be the best way to get the total of digits, however the s.length casting gives the error.
You did not invoke the length method.
You should use int size=static_cast<int>(s.length());: notice the call operator at the end of the length method name.
However, if by doing this, you are trying to convert the string to an integer, this is wrong. This only gives you the number of characters in the string.

How to make gcc/g++ warn on comparing signed and unsigned char

I have the following piece of code:
#include <stdlib.h>
#include <stdio.h>
void test(unsigned char * arg) { }
int main() {
char *pc = (char *) malloc(1);
unsigned char *pcu = (unsigned char *) malloc(1);
*pcu = *pc = -1; /* line 10 */
if (*pc == *pcu) puts("equal"); else puts("not equal"); /* line 12 */
pcu = pc; /* line 14 */
if (pcu == pc) { /* line 16 */
test(pc); /* line 18 */
}
return 0;
}
If I compile it with gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) (but it is not limited to this particular version) with options
gcc a.c -pedantic -Wall -Wextra -Wsign-conversion -Wno-unused-parameter; ./a.out
I get the following warnings
test.c: In function ‘main’:
test.c:10:21: warning: conversion to ‘unsigned char’ from ‘char’ may change the sign of the result [-Wsign-conversion]
test.c:14:13: warning: pointer targets in assignment differ in signedness [-Wpointer-sign]
test.c:16:17: warning: comparison of distinct pointer types lacks a cast [enabled by default]
test.c:18:17: warning: pointer targets in passing argument 1 of ‘test’ differ in signedness [-Wpointer-sign]
test.c:4:6: note: expected ‘unsigned char *’ but argument is of type ‘char *’
not equal
g++ warnings/errors are similar. I hope I understand why the comparison on line 12 is evaluated to false, but is there any way to get a warning also in such cases? If not, is there some principial difference between line 12 and the lines which cause warnings? Is there any specific reason why comparison of char and unsigned char shouldn't deserve its warning? Because at least at first glance, line 12 seems to me more "dangerous" than e.g. line 16.
A short "story behind": I have to put together pieces of code from various sources. Some of them use char and some of them use unsigned char. -funsigned-char would work fine, but I am forced to avoid it and rather to add proper type conversions. That's why such a warning would be useful for me, because now, if I forget to add a type conversion in such a case, the program silently fails.
Thanks in advance, P.
I believe this is caused by integer promotion.
When you deal with char or short, what C actually does (and this is defined by the standard, not the implementation) is promote those types to int before doing any operations. The theory, I think, is that int is supposed to be the natural size used by the underlying machine, and therefore the fastest, most efficient size; in fact, most architectures will do this conversion on loading a byte without being asked.
Since both signed char and unsigned char will fit happily within the range of a signed int, the compiler uses that for both, and the comparison becomes a pure signed comparison.
When you have a mismatched type on the left-hand-side of the expression (lines 10 and 14) then it needs to convert that back to the smaller type, but it can't, so you get a warning.
When you compared the mismatching pointers (line 16) and passed the mismatching pointer (line 18), the integer promotion is not in play because you never actually dereference the pointers, and so no integers are ever compared (char is an integer type also, of course).

MFC CString to int

using this code i get an error at atoi's conversion from CString to int:
int nrCentrala; CString idCentrala;
GetDlgItem(IDC_EDIT_IDCENTRALA)->GetWindowText(idCentrala);
nrCentrala = atoi(&idCentrala);
where IDC_EDIT_IDCENTRALA is an edit control.
Error 7 error C2664: 'atoi' : cannot convert parameter 1 from 'CString *' to 'const char *'
CString provides an overloaded operator for LPCTSTR. Also, use _tstoi instead, just in case you're compiling with Unicode libraries, e.g.
nrCentrala = _tstoi(idCentrala);
You pass pointer to CString (CString* type) instead of const char* which is expected by atoi(). Correct call is nrCentrala = atoi(idCentrala.GetString());

GCC error when compiling: "lvalue required as left operand of assignment" with function pointer

I have a C code which records a procedure address in an array
void* lpProcAddress[5];
typedef unsigned long (*MyFunction_TYPE) (void*);
#define MyFunctionInArray ( (MyFunction_TYPE) lpProcAddress[0] )
unsigned long AnyFunction ( void* lpPointerToAny )
{
/* Some Code */
return 0;
}
int main()
{
MyFunctionInArray =
AnyFunction; // Displays: "error: lvalue required as left operand of assignment"
}
GCC displays "error: lvalue required as left operand of assignment".
How can I fix this?
For my purpose, I could not call directly AnyFunction().
This will expand to:
(type)xxx = ...
This is not legal. However, you could use something like:
* (type *)& xxx = ...
Try assigning to lpProcAddress[0] directly instead of to MyFunctionInArray.
This should work and you can just keep it that way.
However, if you are interested in why it did not work with your define keep reading, there is a way to do that too:
What you are doing in your #define is cast a pointer-type to MyFunction_TYPE
1) you dont really need to cast the pointer-array to anything, you can just assign the function-pointers into its slots
2) if you really want to cast the pointer-array before assigning into it you have to cast it to a function-pointer-type (and do that before dereferencing so use parenthesis before [0]).
Instead of defining lpProcAddress as void* why not just define as MyFunction_TYPE, e.g.:
typedef unsigned long (*MyFunction_TYPE) (void*);
MyFunction_TYPE lpProcAddress[5];
Then in your main function you can just do:
lpProcAddress[0] = AnyFunction;
Without needing to care about casting.
Likewise to call the function you can then just do:
result = lpProcAddress[0]( some_ptr );

Resources