Static Initialization Fiasco - On Purpose - c++

Just for fun, I was investigating the order of dynamic initialization of static objects.
In a file name t.h, I put
struct T {
static std::vector<std::string> me;
static int add(std::string s) { me.push_back(s); return me.size(); }
};
(Plus needed headers for vector and string.)
"std::vector T::me" is in t.cpp.
The file main.cpp prints out the values in T::me:
#include "t.h"
#include <iostream>
using namespace std;
int main()
{
T::me.push_back("main");
cout << "T::me.size()=" << T::me.size() << endl;
for (unsigned i = 0; i<T::me.size(); ++i) {
cout << i << "-" << T::me[i] << endl;
}
return 0;
}
next, I create "a.cpp" and put the following in it:
#include "t.h"
int a = T::add("a");
Do the similar for file b.cpp and c.cpp using "b" and "c" as appropriate.
Compile using g++ *.cpp, then run ./a.out. The order of static initialization from compilation unit to compilation unit is unspecified. In my case it is consistently in reverse alphabetical order. I get:
3 - c
2 - b
1 - a
0 - main
No problems so far.
Now I create u.cpp like a.cpp but using "u". Recompile/rerun, "u" does not show up in the list.
Is it because I never referenced u? I never referenced a,b,c, but I change main:
#include "t.h"
#include <iostream>
using namespace std;
extern int u;
int main()
{
cout << "u=" << u << endl;
T::me.push_back("main");
cout << "T::me.size()=" << T::me.size() << endl;
for (unsigned i = 0; i<T::me.size(); ++i) {
cout << i << "-" << T::me[i] << endl;
}
return 0;
}
The program prints out "u=2", but "u" is not in the list. Shouldn't u have been dynamically initialized before use and, therefore, T::me have been updated to include "u"? I think there should be a better explanation than that u comes after t in the alphabet.

I've got it. Simple, really.
T::me is zero initialized statically according to the rules of C++. There is a constructor, however, to run dynamically. There's no guarantee when that constructor runs. It is apparently - in this case - running after u is initialized.

It seems that the compilation linking order matters:
g++ -o m a.cpp u.cpp t.cpp main.cpp
gives
a=2
u=1
T::me.size()=3
0-u
1-a
2-main
but
g++ -o m main.cpp t.cpp a.cpp u.cpp
gives
a=2
u=1
T::me.size()=1
0-main
and reversing a.cpp and u.cpp in the last case causes a=1 and u=2.
Interesting!

Related

Logical AND operator on negative number in C

there!! Why's the output different in both codes whereas logic is same!!
Code 1:
#include <iostream>
using namespace std;
int main() {
int a, b, c, d;
a = b = 1;
c = a || --b;
d = a-- && --b;
cout << a << "\t" << b << "\t" << c << "\t" << d << "\n";
}
Output:
~ ❯ g++ main.cpp && ./a.out
0 0 1 0
Code 2:
#include <iostream>
using namespace std;
int main() { cout << -1 && 1; }
Output:
~ ❯ g++ main.cpp && ./a.out
-1~ ❯
Code 3:
#include <iostream>
using namespace std;
int main() { cout << 1 && -1; }
Output:
~ ❯ g++ main.cpp && ./a.out
1~ ❯
I guess it's doing bitwise operation. But I'm not sure, please help.
Moreover, I tried same in C.
#include <stdio.h>
int main() {
printf("%d\n", -1 && 1);
printf("%d\n", 1 && -1);
}
Output:
~ ❯ cc -Wall main.c && ./a.out
1
1
It's very confusing. I think it's implementation-dependent as both C and C++ compiler behaved differently. Please spread some light on it.
As people already disclosed, the issue is that cout << 1 is what is first executed during runtime, then && -1, because that's how the operation order works.
However, if you change your command to cout << (1 && -1);, the order changes, so that the parenthesis is first executed, then the output of the operation is passed onto cout.
Lastly, although not importart to the question, putting an endl to the end of your couts is common practice, something like this: cout << (1 && -1) << endl;

Unused variable warning even when explicitly using it inside IF statement

I am trying to create (using C++17) a simple debug header that only executes some lines of code if the flag LOGGER_DEBUG_MODE is enabled. This is how my header is defined (I also tried using { x; } instead of x but the warning persists):
debug.h
#ifndef _HDEBUG
#define _HDEBUG
static bool LOGGER_DEBUG_MODE = true;
#define R_DEBUG(x) if(LOGGER_DEBUG_MODE == true) x
#endif
I included debug.h and at some point of my code I call the macro function R_DEBUG to print some values:
logger_adc.cpp
double anlg_device_t::eval_formula()
{
double result = -9999;
try
{
result = parser.Eval();
}
catch (mu::Parser::exception_type &e)
{
std::cout << e.GetMsg() << std::endl;
}
R_DEBUG(std::cout << "Eval Result: " << result << std::endl);
return result;
}
I expected everything to work properly but when I run the makefile I got this warning:
inc/debug.h:5:14: warning: 'LOGGER_DEBUG_MODE' defined but not used [-Wunused-variable]
static bool LOGGER_DEBUG_MODE = true;
I thought that my definition was messed up but after checking the temporary files created by g++, it appears that the preprocessor did everything as I expected:
logger_adc.ii
double anlg_device_t::eval_formula()
{
double result = -9999;
try
{
result = parser.Eval();
}
catch (mu::Parser::exception_type &e)
{
std::cout << e.GetMsg() << std::endl;
}
if(LOGGER_DEBUG_MODE == true) std::cout << "Eval Result: " << result << std::endl;
return result;
}
Why do I get the warning message even when the variable LOGGER_DEBUG_MODE is clearly being used inside the if statement? Did I mess up something obvious that I'm not picking up? My compile flags for the object files (where the warning occurs) are g++ -Wall -Wextra -O1 -g -std=c++17 -save-temps=obj -Iinc -I/usr/local/include -c plus pkg-config --cflags --libs libmodbus
If needed, this is my main function:
main.cpp
#include "logger_adc.h"
int main()
{
anlg_device_t test (ADC_CHIP_1, 1, 18, 1, 1, true);
test.set_formula("2*x","x", test.get_voltage_ptr());
std::cout << "Test Voltage: " << test.get_voltage() << std::endl << "Test Relative: " << test.get_relative() << std::endl;
std::cout << "Test Formula (2*x): " << test.eval_formula() << std::endl;
return 0;
}
Thanks in advance!
You have a header that defines a static bool LOGGER_DEBUG_MODE =true;. If you include that header in multiple C++ files then each file will gets its own copy of that bool.
In your main.cpp you aren't using R_DEBUG so the copy of that bool (which presumably comes from including logger_adc.h ) is indeed unused in that file.
Possible solutions are:
You should make it so you only have a single copy of that bool (declare it in the header with extern and define it in a single C++ file.
Use build defines instead of runtime checks
etc

Why would a working main function show this intellisense error?

I'm writing a short program to convert a string (consisting of numbers) to an integer. The code runs ok but I keep getting an odd intellisense error on the "int" part of the int main() declaration. The error text is: this declaration has no storage class or type specifier
and shows the first two letters (the "in") in white and the last (the "t") in the yellow that recognized function names are usually tagged with.
Does anyone know what this might be? Is it just an intellisense anomaly or is there something wrong with my code?
Here's the full code listing:
#include <iostream>
#include <string>
int stringConvert(std::string);
int main()
{
std::string str("123");
int stringNum = stringConvert(str);
std::cout << str << " --> " << stringNum << std::endl;
return 0;
}
int stringConvert(std::string stringIn)
{
int n = std::stoi(stringIn);
std::cout << "String conversion completed" << std::endl;
return n;
}

How to use vectors to find mean and standard deviation

This is the assignment:
Write two functions that calculate the mean and standard deviation.
Your functions shall implement the following prototypes:
double mean(vector<double>x);
double sd(vector<double>x);
b. Place these functions in a file named “statfun.cpp”.
c. Place their function definitions in a file named “statfun.h”.
Write a main() function in a file named “lab1.cpp”.
Prompt the user to input 10 floating-point values and store them in a vector v.
Print vector v on a single line with each element separated by a space.
Call your functions mean(v) and sd(v) ...
I know how to code the formula for mean, but I'm not sure how to code the formula for standard deviation using vectors. I'm even less sure of how to do this with different files involved. I'm fully aware my code is garbage, but there are so many things I'm not sure of, I don't know what to tackle first.
Edit: Updated the code
//statfun.h
#include <iostream>
#include <vector>
#ifndef STATFUN_H
#define STATFUN_H
using namespace std;
double mean(vector<double> v);
double sd(vector<double> v);
#endif
//statfun.cpp
#include <iostream>
#include <cmath>
#include <vector>
#include "statfun.h"
#ifndef STATFUN_CPP
#define STATFUN_CPP
using namespace std;
double mean(const vector<double> v) {
double result;
double sumVal = 0.0; //Calculating sum of all values
for (int i = 0; i < v.size(); ++i) {
sumVal = sumVal + v.at(i);
}
result = sumVal / v.size(); //Calculating mean
return result;
}
double sd(const vector<double> v) {
double total = 0;
for (int i = 0; i < 10; ++i) { //Calcuating standard deviation
double mean_value = mean(v);
int length = v.size()
total = total + (val - mean_value)*(val - mean_value);
}
return sqrt(total / length);
}
#endif
//lab1.cpp
#include "statfun.cpp"
#include <iomanip>
using namespace std;
vector<double> v;
int main() {
cout << "Enter 10 numbers: " << endl;
float userInput = 0;
for (int i = 0; i < 10; ++i) {
cin >> userInput;
v.push_back(userInput);
}
for (int i = 0; i < 10; ++i) {
cout << v.at(i) << " ";
}
cout << endl;
cout.precision(3);
cout << mean(v) << " " << sd(v) << endl;
cout.precision(5);
cout << scientific << mean(v) << " " << sd(v) << endl;
return 0;
}
You made many mistakes and your code has much to improve.
Let me show you me by me.
The header
Since one file can include header multiple times, to prevent any side effect of this, an include guard is required for each header file.
// statfun.h
#ifndef __statfun_H__
# define __statfun_H__
# include <vector>
double mean(const std::vector<double>&);
double sd(const std::vector<double>&);
#endif
BTW, a function declaration can abbreviate the arguments' name.
Reference
The second mistake you made is that you didn't use reference. In c++, an object is by default passed by value.
Note: This is just like R, except it doesn't have language level copy-on-write semantics, but user-defined class can implement this, classes defined in std namespace can also implement this.
So in order to prevent costy copy, reference is made.
double mean(const std::vector<double>&);
Here I used const left-value reference (const &), since mean will not modify the vector passed in.
Function blocks.
In c++, a function is defined as below:
return_value func_name(type1 arg1 /* , type2 arg2, ... */)
{
// The function body goes here:
}
So
// statfun.cpp
// c++11
#include "statfun.h"
#include <cmath>
double mean(const std::vector<double> &v)
{
double sum = 0;
for (auto &each: v)
sum += each;
return sum / v.size();
}
double sd(const std::vector<double> &v)
{
double square_sum_of_difference = 0;
double mean_var = mean(v);
auto len = v.size();
double tmp;
for (auto &each: v) {
tmp = each - mean_var;
square_sum_of_difference += tmp * tmp;
}
return std::sqrt(square_sum_of_difference / (len - 1));
}
Compile-time variable type deduction
As you might have noticed in the code above, I used auto len = v.size(), which is a c++11 language feature -- auto.
Since c++11, c++ can deduce the return type of function calls at compile-time. So instead of define variable like typename std::vector<double>::size_type len = v.size(), we now have auto len = v.size().
range-for loop
If you have learnt python, then you must know range-for. Since c++11, c++ can also do this:
for (auto &each: v) {
// Loop body
}
where v can be std::vector or any other container in c++.
IO error check
Last but not least, you didn't check if any of these IO you performed on std::cout or std::cin succeeds or not!
Using std::cout or std::cin, you have to check stream state by std::cout.fail() every time after you performed an IO, or use the following code:
std::cout.exceptions(std::ios_base::failbit | std::ios_base::badbit);
std::cin.exceptions(std::ios_base::failbit | std::ios_base::badbit);
To make std::cout and std::cin throws when an IO fails.
I personally like to not handle this error and let the exception terminates the program, since there is nothing you can do to cleanup and resume the control flow of the program.
Below is the last piece of code:
// lab1.cpp
// c++11
#include "statfun.h"
#include <iostream>
auto get_use_input() -> std::vector<double>
{
std::vector<double> v;
v.reserve(10);
double userInput;
for (int i = 0; i != 10; ++i) {
std::cout << "Please enter the " << i + 1 << " number: ";
std::cin >> userInput;
std::cout << std::endl;
v.push_back(userInput);
}
return v;
}
void print_vec(const std::vector<double> &v)
{
std::cout << "Vector: ";
for (auto &each: v)
std::cout << each << " ";
std::cout << std::endl;
}
int main() {
// Configure std::cout and std::cin to throw if io fails.
std::cout.exceptions(std::ios_base::failbit | std::ios_base::badbit);
std::cin.exceptions(std::ios_base::failbit | std::ios_base::badbit);
/*
* With "-O3" or [c++17, copy elision](https://en.cppreference.com/w/cpp/language/copy_elision),
* the cost of initializing an object using the return value of anther function is nearly zero.
*/
std::vector<double> v = get_use_input();
print_vec(v);
std::cout.precision(3);
std::cout << "mean: " << mean(v) << " sd: " << sd(v) << std::endl;
std::cout.precision(5);
std::cout <<std::scientific << "mean: " << mean(v) << " sd: " << sd(v) << std::endl;
return 0;
}
To build this program, you must have a c++ compiler that supports c++11 and pass -std=c++11 to the compiler.
PS: You can also use -std=c++14 or -std=c++17.
A simple Makefile to build the program:
cxx = ${CXX}
# The flags
CPPFLAGS := -std=c++11
# The two line below is the flags I used for clang++-8
# CPPFLAGS := -std=c++17 -Ofast -pipe -flto
# LDFLAGS := -flto -pipe -Wl,--icf=all,-O2,--as-needed,--strip-all,--plugin-opt=O3
lab1: lab1.o statfun.o
$(CXX) $(LDFLAGS) $^ -o $#
statfun.o: statfun.h
lab1.o: statfun.h
.PHONY: clean
rm -f lab1.o statfun.o lab
I believe your first issue is in understanding the file structure of your stats assignment. Tackle this first. Understanding headers. More on headers and function calls from other files.
The .cpp files will contain implementation of logic, the .h files are headers that should declare definitions of objects and functions. When you include files at the top of your code, generally think of this as having all the code from that file above the current file.
Example:
statfun.h
double mean(vector<double> v);
// other **declaration** stuff....
lab1.cpp at the top of the file
#include "statfun.h" // equivalent to copy/pasting 'double mean(vector<double> v); and other declarations' into your lab1.cpp
// This is to help with cleanliness of your file structure.
// You'll thank yourself when projects become bigger.
Note: lab1.cpp includes statfun.cpp which includes statfun.h; implicitly, lab1.cpp includes statfun.h which means you don't have to include statfun.h in lab1, although typically the header is included, not the cpp file. You must avoid circular dependencies which you do with the ifndef.
b. statfun.cpp should be the place where you code all of your logic for the mean and standard deviation.
example:
statfun.cpp
double mean(vector<double> v) {
// Your mean calculation logic here.
return mean;
}
double sd(vector<double> x) {
// Your standard deviation calculation logic here.
return sd;
}
c.
So you have lab1.cpp which will be compiled to produce some runnable binary. As the entry point of your program, it should include an int main() function. This main function needs to ask for user input (search the webs for how to take std input).
Store the standard input as a vector (this is still in your main function).
Use cout to print to standard out. 'cout << name_of_variable_with_vector_input_from_user;' (still in your int main())
Call/use the functions you wrote in statfun.cpp (notably mean() and sd()). Maybe store their return values in a variable to use later. Since you need to call the statfun functions here, the lab1.cpp entry file must include statfun.h so that it knows what code to execute when you call those functions.
Now that this file structure logic is complete. A simple way to calculate std deviation in pseudocode:
statfun.madeuplanguage
type sd(vector<type> values) {
type total = 0;
type mean_value = mean(values);
for val in values {
total += (val - mean_value)^2;
}
total /= values.length;
return sqrt(total);
}
This in mind, I would structure the lab1.cpp as follows.
lab1.cpp
int main() {
vector<double> v;
// take input and store in v.
// std out - v
double mean_val = mean(v);
double std_dev = sd(v);
// std out - mean_val and std_dev
}
If you have any questions about implementing the above pseudocode in C++, great! It's your assignment/class, so take care to search the webs in doing extremely specific things in C++ (e.g. iterating on a vector, squaring, square rooting, etc...). Good luck learning.

C++ using ldap_bind from ldap.h

I'm trying to use ldap_bind, but get an this error.
error: âldap_bindâ was not declared in this scope
code:
#include <lber.h>
#include <ldap.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
LDAP *ld;
char *ldap_host = "ldap://localhost";
int ldap_port = 389;
int auth_method = LDAP_AUTH_SIMPLE;
int desired_version = LDAP_VERSION3;
char *root_dn = "ou=people,dc=localhost,dc=local";
char *root_ps = "password";
int result;
result = ldap_initialize(&ld, ldap_host);
cout << "result: " << result << endl;
result = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &desired_version);
cout << "result: " << result << endl;
result = ldap_bind_s(ld, root_dn, root_ps, auth_method);
cout << "result: " << result << endl;
}
I'm compiling with this command
g++ ldap.cpp -llber -lldap -o prog
TIA
I've no experience with OpenLDAP, but from the header it seems you need:
extern "C" {
# define LDAP_DEPRECATED
# include <ldap.h>
# include <lber.h>
}
It leads to some compiling errors in current version, since in the ldap.h use #if LDAP_DEPRECATED instead of #ifdef, give the MACRO a value:
#define LDAP_DEPRECATED 1
And it is good to go.
Dont use ldap_bind. Its deprecated. Rather use ldap_sasl_bind.
ldap.h has deprecated a lot of functions for mostly security reasons
Check out the following command which lists all the deprecated functions
grep deprecate < /usr/include/ldap.h
On *nix systems, or any system that let's you specify compilation flags, you can add the following to your list of flags:
-DLDAP_DEPRECATED
This allows you to use the deprecated deprecated features without having to add defines to the top of all of your source/header files.